+++ /dev/null
-/** @file\r
- ConsoleOut Routines that speak VGA.\r
-\r
-Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
-\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "BiosVideo.h"\r
-\r
-//\r
-// EFI Driver Binding Protocol Instance\r
-//\r
-EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding = {\r
- BiosVideoDriverBindingSupported,\r
- BiosVideoDriverBindingStart,\r
- BiosVideoDriverBindingStop,\r
- 0x3,\r
- NULL,\r
- NULL\r
-};\r
-\r
-//\r
-// Global lookup tables for VGA graphics modes\r
-//\r
-UINT8 mVgaLeftMaskTable[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };\r
-\r
-UINT8 mVgaRightMaskTable[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };\r
-\r
-UINT8 mVgaBitMaskTable[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };\r
-\r
-//\r
-// Save controller attributes during first start\r
-//\r
-UINT64 mOriginalPciAttributes;\r
-BOOLEAN mPciAttributesSaved = FALSE;\r
-\r
-EFI_GRAPHICS_OUTPUT_BLT_PIXEL mVgaColorToGraphicsOutputColor[] = {\r
- { 0x00, 0x00, 0x00, 0x00 },\r
- { 0x98, 0x00, 0x00, 0x00 },\r
- { 0x00, 0x98, 0x00, 0x00 },\r
- { 0x98, 0x98, 0x00, 0x00 },\r
- { 0x00, 0x00, 0x98, 0x00 },\r
- { 0x98, 0x00, 0x98, 0x00 },\r
- { 0x00, 0x98, 0x98, 0x00 },\r
- { 0x98, 0x98, 0x98, 0x00 },\r
- { 0x10, 0x10, 0x10, 0x00 },\r
- { 0xff, 0x10, 0x10, 0x00 },\r
- { 0x10, 0xff, 0x10, 0x00 },\r
- { 0xff, 0xff, 0x10, 0x00 },\r
- { 0x10, 0x10, 0xff, 0x00 },\r
- { 0xf0, 0x10, 0xff, 0x00 },\r
- { 0x10, 0xff, 0xff, 0x00 },\r
- { 0xff, 0xff, 0xff, 0x00 }\r
-};\r
-\r
-//\r
-// Standard timing defined by VESA EDID\r
-//\r
-VESA_BIOS_EXTENSIONS_EDID_TIMING mEstablishedEdidTiming[] = {\r
- //\r
- // Established Timing I\r
- //\r
- {800, 600, 60},\r
- {800, 600, 56},\r
- {640, 480, 75},\r
- {640, 480, 72},\r
- {640, 480, 67},\r
- {640, 480, 60},\r
- {720, 400, 88},\r
- {720, 400, 70},\r
- //\r
- // Established Timing II\r
- //\r
- {1280, 1024, 75},\r
- {1024, 768, 75},\r
- {1024, 768, 70},\r
- {1024, 768, 60},\r
- {1024, 768, 87},\r
- {832, 624, 75},\r
- {800, 600, 75},\r
- {800, 600, 72},\r
- //\r
- // Established Timing III\r
- //\r
- {1152, 870, 75}\r
-};\r
-\r
-/**\r
- Supported.\r
-\r
- @param This Pointer to driver binding protocol\r
- @param Controller Controller handle to connect\r
- @param RemainingDevicePath A pointer to the remaining portion of a device\r
- path\r
-\r
- @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this\r
- driver, Otherwise, this controller cannot be\r
- managed by this driver\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BiosVideoDriverBindingSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- PCI_TYPE00 Pci;\r
- EFI_DEV_PATH *Node;\r
-\r
- //\r
- // See if the Legacy BIOS Protocol is available\r
- //\r
- Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Open the IO Abstraction(s) needed to perform the supported test\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &PciIo,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
- return Status;\r
- }\r
-\r
- if (Status == EFI_ALREADY_STARTED) {\r
- //\r
- // If VgaMiniPort protocol is installed, EFI_ALREADY_STARTED indicates failure,\r
- // because VgaMiniPort protocol is installed on controller handle directly.\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiVgaMiniPortProtocolGuid,\r
- NULL,\r
- NULL,\r
- NULL,\r
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- return EFI_ALREADY_STARTED;\r
- }\r
- }\r
- //\r
- // See if this is a PCI Graphics Controller by looking at the Command register and\r
- // Class Code Register\r
- //\r
- Status = PciIo->Pci.Read (\r
- PciIo,\r
- EfiPciIoWidthUint32,\r
- 0,\r
- sizeof (Pci) / sizeof (UINT32),\r
- &Pci\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_UNSUPPORTED;\r
- goto Done;\r
- }\r
-\r
- Status = EFI_UNSUPPORTED;\r
- if (Pci.Hdr.ClassCode[2] == 0x03 || (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01)) {\r
-\r
- Status = EFI_SUCCESS;\r
- //\r
- // If this is a graphics controller,\r
- // go further check RemainingDevicePath validation\r
- //\r
- if (RemainingDevicePath != NULL) {\r
- Node = (EFI_DEV_PATH *) RemainingDevicePath;\r
- //\r
- // Check if RemainingDevicePath is the End of Device Path Node,\r
- // if yes, return EFI_SUCCESS\r
- //\r
- if (!IsDevicePathEnd (Node)) {\r
- //\r
- // If RemainingDevicePath isn't the End of Device Path Node,\r
- // check its validation\r
- //\r
- if (Node->DevPath.Type != ACPI_DEVICE_PATH ||\r
- Node->DevPath.SubType != ACPI_ADR_DP ||\r
- DevicePathNodeLength(&Node->DevPath) < sizeof(ACPI_ADR_DEVICE_PATH)) {\r
- Status = EFI_UNSUPPORTED;\r
- }\r
- }\r
- }\r
- }\r
-\r
-Done:\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Install Graphics Output Protocol onto VGA device handles.\r
-\r
- @param This Pointer to driver binding protocol\r
- @param Controller Controller handle to connect\r
- @param RemainingDevicePath A pointer to the remaining portion of a device\r
- path\r
-\r
- @return EFI_STATUS\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BiosVideoDriverBindingStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
- UINTN Flags;\r
- UINT64 Supports;\r
-\r
- //\r
- // Initialize local variables\r
- //\r
- PciIo = NULL;\r
- ParentDevicePath = NULL;\r
-\r
- //\r
- //\r
- // See if the Legacy BIOS Protocol is available\r
- //\r
- Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Prepare for status code\r
- //\r
- Status = gBS->HandleProtocol (\r
- Controller,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID **) &ParentDevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Open the IO Abstraction(s) needed\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &PciIo,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Save original PCI attributes\r
- //\r
- if (!mPciAttributesSaved) {\r
- Status = PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationGet,\r
- 0,\r
- &mOriginalPciAttributes\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- mPciAttributesSaved = TRUE;\r
- }\r
-\r
- //\r
- // Get supported PCI attributes\r
- //\r
- Status = PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationSupported,\r
- 0,\r
- &Supports\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- Supports &= (UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);\r
- if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) {\r
- Status = EFI_UNSUPPORTED;\r
- goto Done;\r
- }\r
-\r
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
- EFI_PROGRESS_CODE,\r
- EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE,\r
- ParentDevicePath\r
- );\r
- //\r
- // Enable the device and make sure VGA cycles are being forwarded to this VGA device\r
- //\r
- Status = PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationEnable,\r
- EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | Supports,\r
- NULL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
- EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
- EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_RESOURCE_CONFLICT,\r
- ParentDevicePath\r
- );\r
- goto Done;\r
- }\r
- //\r
- // Check to see if there is a legacy option ROM image associated with this PCI device\r
- //\r
- Status = LegacyBios->CheckPciRom (\r
- LegacyBios,\r
- Controller,\r
- NULL,\r
- NULL,\r
- &Flags\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- //\r
- // Post the legacy option ROM if it is available.\r
- //\r
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
- EFI_PROGRESS_CODE,\r
- EFI_P_PC_RESET,\r
- ParentDevicePath\r
- );\r
- Status = LegacyBios->InstallPciRom (\r
- LegacyBios,\r
- Controller,\r
- NULL,\r
- &Flags,\r
- NULL,\r
- NULL,\r
- NULL,\r
- NULL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
- EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
- EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,\r
- ParentDevicePath\r
- );\r
- goto Done;\r
- }\r
-\r
- if (RemainingDevicePath != NULL) {\r
- if (IsDevicePathEnd (RemainingDevicePath) &&\r
- (FeaturePcdGet (PcdBiosVideoCheckVbeEnable) || FeaturePcdGet (PcdBiosVideoCheckVgaEnable))) {\r
- //\r
- // If RemainingDevicePath is the End of Device Path Node,\r
- // don't create any child device and return EFI_SUCESS\r
- Status = EFI_SUCCESS;\r
- goto Done;\r
- }\r
- }\r
-\r
- //\r
- // Create child handle and install GraphicsOutputProtocol on it\r
- //\r
- Status = BiosVideoChildHandleInstall (\r
- This,\r
- Controller,\r
- PciIo,\r
- LegacyBios,\r
- ParentDevicePath,\r
- RemainingDevicePath\r
- );\r
-\r
-Done:\r
- if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {\r
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
- EFI_PROGRESS_CODE,\r
- EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE,\r
- ParentDevicePath\r
- );\r
-\r
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
- EFI_PROGRESS_CODE,\r
- EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_NOT_DETECTED,\r
- ParentDevicePath\r
- );\r
- if (!HasChildHandle (Controller)) {\r
- if (mPciAttributesSaved) {\r
- //\r
- // Restore original PCI attributes\r
- //\r
- PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationSet,\r
- mOriginalPciAttributes,\r
- NULL\r
- );\r
- }\r
- }\r
- //\r
- // Release PCI I/O Protocols on the controller handle.\r
- //\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Stop.\r
-\r
- @param This Pointer to driver binding protocol\r
- @param Controller Controller handle to connect\r
- @param NumberOfChildren Number of children handle created by this driver\r
- @param ChildHandleBuffer Buffer containing child handle created\r
-\r
- @retval EFI_SUCCESS Driver disconnected successfully from controller\r
- @retval EFI_UNSUPPORTED Cannot find BIOS_VIDEO_DEV structure\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BiosVideoDriverBindingStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BOOLEAN AllChildrenStopped;\r
- UINTN Index;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
-\r
- AllChildrenStopped = TRUE;\r
-\r
- if (NumberOfChildren == 0) {\r
- //\r
- // Close PCI I/O protocol on the controller handle\r
- //\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- return EFI_SUCCESS;\r
- }\r
-\r
- for (Index = 0; Index < NumberOfChildren; Index++) {\r
- Status = BiosVideoChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]);\r
-\r
- if (EFI_ERROR (Status)) {\r
- AllChildrenStopped = FALSE;\r
- }\r
- }\r
-\r
- if (!AllChildrenStopped) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if (!HasChildHandle (Controller)) {\r
- if (mPciAttributesSaved) {\r
- Status = gBS->HandleProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &PciIo\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Restore original PCI attributes\r
- //\r
- Status = PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationSet,\r
- mOriginalPciAttributes,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
- }\r
-\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Install child handles if the Handle supports MBR format.\r
-\r
- @param This Calling context.\r
- @param ParentHandle Parent Handle\r
- @param ParentPciIo Parent PciIo interface\r
- @param ParentLegacyBios Parent LegacyBios interface\r
- @param ParentDevicePath Parent Device Path\r
- @param RemainingDevicePath Remaining Device Path\r
-\r
- @retval EFI_SUCCESS If a child handle was added\r
- @retval other A child handle was not added\r
-\r
-**/\r
-EFI_STATUS\r
-BiosVideoChildHandleInstall (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE ParentHandle,\r
- IN EFI_PCI_IO_PROTOCOL *ParentPciIo,\r
- IN EFI_LEGACY_BIOS_PROTOCOL *ParentLegacyBios,\r
- IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BIOS_VIDEO_DEV *BiosVideoPrivate;\r
- PCI_TYPE00 Pci;\r
- ACPI_ADR_DEVICE_PATH AcpiDeviceNode;\r
- BOOLEAN ProtocolInstalled;\r
-\r
- //\r
- // Allocate the private device structure for video device\r
- //\r
- BiosVideoPrivate = (BIOS_VIDEO_DEV *) AllocateZeroPool (\r
- sizeof (BIOS_VIDEO_DEV)\r
- );\r
- if (NULL == BiosVideoPrivate) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
- }\r
-\r
- //\r
- // See if this is a VGA compatible controller or not\r
- //\r
- Status = ParentPciIo->Pci.Read (\r
- ParentPciIo,\r
- EfiPciIoWidthUint32,\r
- 0,\r
- sizeof (Pci) / sizeof (UINT32),\r
- &Pci\r
- );\r
- if (EFI_ERROR (Status)) {\r
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
- EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
- EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,\r
- ParentDevicePath\r
- );\r
- goto Done;\r
- }\r
- BiosVideoPrivate->VgaCompatible = FALSE;\r
- if (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01) {\r
- BiosVideoPrivate->VgaCompatible = TRUE;\r
- }\r
-\r
- if (Pci.Hdr.ClassCode[2] == 0x03 && Pci.Hdr.ClassCode[1] == 0x00 && Pci.Hdr.ClassCode[0] == 0x00) {\r
- BiosVideoPrivate->VgaCompatible = TRUE;\r
- }\r
-\r
- if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable)) {\r
- //\r
- // Create EXIT_BOOT_SERIVES Event\r
- //\r
- Status = gBS->CreateEventEx (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- BiosVideoNotifyExitBootServices,\r
- BiosVideoPrivate,\r
- &gEfiEventExitBootServicesGuid,\r
- &BiosVideoPrivate->ExitBootServicesEvent\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- }\r
-\r
- //\r
- // Initialize the child private structure\r
- //\r
- BiosVideoPrivate->Signature = BIOS_VIDEO_DEV_SIGNATURE;\r
-\r
- //\r
- // Fill in Graphics Output specific mode structures\r
- //\r
- BiosVideoPrivate->HardwareNeedsStarting = TRUE;\r
- BiosVideoPrivate->ModeData = NULL;\r
- BiosVideoPrivate->LineBuffer = NULL;\r
- BiosVideoPrivate->VgaFrameBuffer = NULL;\r
- BiosVideoPrivate->VbeFrameBuffer = NULL;\r
-\r
- //\r
- // Fill in the Graphics Output Protocol\r
- //\r
- BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode;\r
- BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode;\r
-\r
-\r
- //\r
- // Allocate buffer for Graphics Output Protocol mode information\r
- //\r
- BiosVideoPrivate->GraphicsOutput.Mode = (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *) AllocatePool (\r
- sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE)\r
- );\r
- if (NULL == BiosVideoPrivate->GraphicsOutput.Mode) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
- }\r
-\r
- BiosVideoPrivate->GraphicsOutput.Mode->Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (\r
- sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)\r
- );\r
- if (NULL == BiosVideoPrivate->GraphicsOutput.Mode->Info) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
- }\r
-\r
- //\r
- // Assume that Graphics Output Protocol will be produced until proven otherwise\r
- //\r
- BiosVideoPrivate->ProduceGraphicsOutput = TRUE;\r
-\r
- //\r
- // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.\r
- //\r
- if ((RemainingDevicePath == NULL) || (!IsDevicePathEnd (RemainingDevicePath))) {\r
- if (RemainingDevicePath == NULL) {\r
- ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));\r
- AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;\r
- AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;\r
- AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);\r
- SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));\r
-\r
- BiosVideoPrivate->GopDevicePath = AppendDevicePathNode (\r
- ParentDevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode\r
- );\r
- } else {\r
- BiosVideoPrivate->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);\r
- }\r
-\r
- //\r
- // Creat child handle and device path protocol firstly\r
- //\r
- BiosVideoPrivate->Handle = NULL;\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &BiosVideoPrivate->Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- BiosVideoPrivate->GopDevicePath,\r
- NULL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- }\r
-\r
- //\r
- // Fill in the VGA Mini Port Protocol fields\r
- //\r
- BiosVideoPrivate->VgaMiniPort.SetMode = BiosVideoVgaMiniPortSetMode;\r
- BiosVideoPrivate->VgaMiniPort.VgaMemoryOffset = 0xb8000;\r
- BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4;\r
- BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterOffset = 0x3d5;\r
- BiosVideoPrivate->VgaMiniPort.VgaMemoryBar = EFI_PCI_IO_PASS_THROUGH_BAR;\r
- BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR;\r
- BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR;\r
-\r
- //\r
- // Child handle need to consume the Legacy Bios protocol\r
- //\r
- BiosVideoPrivate->LegacyBios = ParentLegacyBios;\r
-\r
- //\r
- // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally\r
- //\r
- BiosVideoPrivate->PciIo = ParentPciIo;\r
-\r
- //\r
- // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output\r
- //\r
- if (FeaturePcdGet (PcdBiosVideoCheckVbeEnable)) {\r
- Status = BiosVideoCheckForVbe (BiosVideoPrivate);\r
- DEBUG ((EFI_D_INFO, "BiosVideoCheckForVbe - %r\n", Status));\r
- } else {\r
- Status = EFI_UNSUPPORTED;\r
- }\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // The VESA BIOS Extensions are not compatible with Graphics Output, so check for support\r
- // for the standard 640x480 16 color VGA mode\r
- //\r
- DEBUG ((EFI_D_INFO, "VgaCompatible - %x\n", BiosVideoPrivate->VgaCompatible));\r
- if (BiosVideoPrivate->VgaCompatible) {\r
- if (FeaturePcdGet (PcdBiosVideoCheckVgaEnable)) {\r
- Status = BiosVideoCheckForVga (BiosVideoPrivate);\r
- DEBUG ((EFI_D_INFO, "BiosVideoCheckForVga - %r\n", Status));\r
- } else {\r
- Status = EFI_UNSUPPORTED;\r
- }\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Free GOP mode structure if it is not freed before\r
- // VgaMiniPort does not need this structure any more\r
- //\r
- if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
- if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
- FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
- BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL;\r
- }\r
- FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
- BiosVideoPrivate->GraphicsOutput.Mode = NULL;\r
- }\r
-\r
- //\r
- // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do\r
- // not produce the Graphics Output protocol. Instead, produce the VGA MiniPort Protocol.\r
- //\r
- BiosVideoPrivate->ProduceGraphicsOutput = FALSE;\r
-\r
- //\r
- // INT services are available, so on the 80x25 and 80x50 text mode are supported\r
- //\r
- BiosVideoPrivate->VgaMiniPort.MaxMode = 2;\r
- }\r
- }\r
-\r
- ProtocolInstalled = FALSE;\r
-\r
- if (BiosVideoPrivate->ProduceGraphicsOutput) {\r
- //\r
- // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol\r
- //\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &BiosVideoPrivate->Handle,\r
- &gEfiGraphicsOutputProtocolGuid,\r
- &BiosVideoPrivate->GraphicsOutput,\r
- &gEfiEdidDiscoveredProtocolGuid,\r
- &BiosVideoPrivate->EdidDiscovered,\r
- &gEfiEdidActiveProtocolGuid,\r
- &BiosVideoPrivate->EdidActive,\r
- NULL\r
- );\r
-\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Open the Parent Handle for the child\r
- //\r
- Status = gBS->OpenProtocol (\r
- ParentHandle,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &BiosVideoPrivate->PciIo,\r
- This->DriverBindingHandle,\r
- BiosVideoPrivate->Handle,\r
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- ProtocolInstalled = TRUE;\r
- }\r
- }\r
-\r
- if (!ProtocolInstalled) {\r
- //\r
- // Install VGA Mini Port Protocol\r
- //\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &ParentHandle,\r
- &gEfiVgaMiniPortProtocolGuid,\r
- &BiosVideoPrivate->VgaMiniPort,\r
- NULL\r
- );\r
- }\r
-\r
-Done:\r
- if (EFI_ERROR (Status)) {\r
- if ((BiosVideoPrivate != NULL) && (BiosVideoPrivate->ExitBootServicesEvent != NULL)) {\r
- gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent);\r
- }\r
- //\r
- // Free private data structure\r
- //\r
- BiosVideoDeviceReleaseResource (BiosVideoPrivate);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Deregister an video child handle and free resources.\r
-\r
- @param This Protocol instance pointer.\r
- @param Controller Video controller handle\r
- @param Handle Video child handle\r
-\r
- @return EFI_STATUS\r
-\r
-**/\r
-EFI_STATUS\r
-BiosVideoChildHandleUninstall (\r
- EFI_DRIVER_BINDING_PROTOCOL *This,\r
- EFI_HANDLE Controller,\r
- EFI_HANDLE Handle\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_IA32_REGISTER_SET Regs;\r
- EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
- EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort;\r
- BIOS_VIDEO_DEV *BiosVideoPrivate;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
-\r
- BiosVideoPrivate = NULL;\r
- GraphicsOutput = NULL;\r
- PciIo = NULL;\r
- Status = EFI_UNSUPPORTED;\r
-\r
- Status = gBS->OpenProtocol (\r
- Handle,\r
- &gEfiGraphicsOutputProtocolGuid,\r
- (VOID **) &GraphicsOutput,\r
- This->DriverBindingHandle,\r
- Handle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- Status = gBS->OpenProtocol (\r
- Handle,\r
- &gEfiVgaMiniPortProtocolGuid,\r
- (VOID **) &VgaMiniPort,\r
- This->DriverBindingHandle,\r
- Handle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort);\r
- }\r
- }\r
-\r
- if (BiosVideoPrivate == NULL) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- //\r
- // Set the 80x25 Text VGA Mode\r
- //\r
- Regs.H.AH = 0x00;\r
- Regs.H.AL = 0x03;\r
- BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
-\r
- Regs.H.AH = 0x11;\r
- Regs.H.AL = 0x14;\r
- Regs.H.BL = 0;\r
- BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
-\r
- //\r
- // Close PCI I/O protocol that opened by child handle\r
- //\r
- Status = gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Handle\r
- );\r
-\r
- //\r
- // Uninstall protocols on child handle\r
- //\r
- if (BiosVideoPrivate->ProduceGraphicsOutput) {\r
- Status = gBS->UninstallMultipleProtocolInterfaces (\r
- BiosVideoPrivate->Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- BiosVideoPrivate->GopDevicePath,\r
- &gEfiGraphicsOutputProtocolGuid,\r
- &BiosVideoPrivate->GraphicsOutput,\r
- &gEfiEdidDiscoveredProtocolGuid,\r
- &BiosVideoPrivate->EdidDiscovered,\r
- &gEfiEdidActiveProtocolGuid,\r
- &BiosVideoPrivate->EdidActive,\r
- NULL\r
- );\r
- }\r
- if (!BiosVideoPrivate->ProduceGraphicsOutput) {\r
- Status = gBS->UninstallMultipleProtocolInterfaces (\r
- Controller,\r
- &gEfiVgaMiniPortProtocolGuid,\r
- &BiosVideoPrivate->VgaMiniPort,\r
- NULL\r
- );\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- gBS->OpenProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &PciIo,\r
- This->DriverBindingHandle,\r
- Handle,\r
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
- );\r
- return Status;\r
- }\r
-\r
- if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable)) {\r
- //\r
- // Close EXIT_BOOT_SERIVES Event\r
- //\r
- gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent);\r
- }\r
-\r
- //\r
- // Release all allocated resources\r
- //\r
- BiosVideoDeviceReleaseResource (BiosVideoPrivate);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Release resource for biso video instance.\r
-\r
- @param BiosVideoPrivate Video child device private data structure\r
-\r
-**/\r
-VOID\r
-BiosVideoDeviceReleaseResource (\r
- BIOS_VIDEO_DEV *BiosVideoPrivate\r
- )\r
-{\r
- if (BiosVideoPrivate == NULL) {\r
- return ;\r
- }\r
-\r
- //\r
- // Release all the resourses occupied by the BIOS_VIDEO_DEV\r
- //\r
-\r
- //\r
- // Free VGA Frame Buffer\r
- //\r
- if (BiosVideoPrivate->VgaFrameBuffer != NULL) {\r
- FreePool (BiosVideoPrivate->VgaFrameBuffer);\r
- }\r
- //\r
- // Free VBE Frame Buffer\r
- //\r
- if (BiosVideoPrivate->VbeFrameBuffer != NULL) {\r
- FreePool (BiosVideoPrivate->VbeFrameBuffer);\r
- }\r
- //\r
- // Free line buffer\r
- //\r
- if (BiosVideoPrivate->LineBuffer != NULL) {\r
- FreePool (BiosVideoPrivate->LineBuffer);\r
- }\r
- //\r
- // Free mode data\r
- //\r
- if (BiosVideoPrivate->ModeData != NULL) {\r
- FreePool (BiosVideoPrivate->ModeData);\r
- }\r
- //\r
- // Free memory allocated below 1MB\r
- //\r
- if (BiosVideoPrivate->PagesBelow1MB != 0) {\r
- gBS->FreePages (BiosVideoPrivate->PagesBelow1MB, BiosVideoPrivate->NumberOfPagesBelow1MB);\r
- }\r
-\r
- if (BiosVideoPrivate->VbeSaveRestorePages != 0) {\r
- gBS->FreePages (BiosVideoPrivate->VbeSaveRestoreBuffer, BiosVideoPrivate->VbeSaveRestorePages);\r
- }\r
-\r
- //\r
- // Free graphics output protocol occupied resource\r
- //\r
- if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
- if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
- FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
- BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL;\r
- }\r
- FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
- BiosVideoPrivate->GraphicsOutput.Mode = NULL;\r
- }\r
- //\r
- // Free EDID discovered protocol occupied resource\r
- //\r
- if (BiosVideoPrivate->EdidDiscovered.Edid != NULL) {\r
- FreePool (BiosVideoPrivate->EdidDiscovered.Edid);\r
- }\r
- //\r
- // Free EDID active protocol occupied resource\r
- //\r
- if (BiosVideoPrivate->EdidActive.Edid != NULL) {\r
- FreePool (BiosVideoPrivate->EdidActive.Edid);\r
- }\r
-\r
- if (BiosVideoPrivate->GopDevicePath!= NULL) {\r
- FreePool (BiosVideoPrivate->GopDevicePath);\r
- }\r
-\r
- FreePool (BiosVideoPrivate);\r
-\r
- return ;\r
-}\r
-\r
-\r
-/**\r
- Generate a search key for a specified timing data.\r
-\r
- @param EdidTiming Pointer to EDID timing\r
-\r
- @return The 32 bit unique key for search.\r
-\r
-**/\r
-UINT32\r
-CalculateEdidKey (\r
- VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming\r
- )\r
-{\r
- UINT32 Key;\r
-\r
- //\r
- // Be sure no conflicts for all standard timing defined by VESA.\r
- //\r
- Key = (EdidTiming->HorizontalResolution * 2) + EdidTiming->VerticalResolution;\r
- return Key;\r
-}\r
-\r
-\r
-/**\r
- Parse the Established Timing and Standard Timing in EDID data block.\r
-\r
- @param EdidBuffer Pointer to EDID data block\r
- @param ValidEdidTiming Valid EDID timing information\r
-\r
- @retval TRUE The EDID data is valid.\r
- @retval FALSE The EDID data is invalid.\r
-\r
-**/\r
-BOOLEAN\r
-ParseEdidData (\r
- UINT8 *EdidBuffer,\r
- VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming\r
- )\r
-{\r
- UINT8 CheckSum;\r
- UINT32 Index;\r
- UINT32 ValidNumber;\r
- UINT32 TimingBits;\r
- UINT8 *BufferIndex;\r
- UINT16 HorizontalResolution;\r
- UINT16 VerticalResolution;\r
- UINT8 AspectRatio;\r
- UINT8 RefreshRate;\r
- VESA_BIOS_EXTENSIONS_EDID_TIMING TempTiming;\r
- VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *EdidDataBlock;\r
-\r
- EdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) EdidBuffer;\r
-\r
- //\r
- // Check the checksum of EDID data\r
- //\r
- CheckSum = 0;\r
- for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; Index ++) {\r
- CheckSum = (UINT8) (CheckSum + EdidBuffer[Index]);\r
- }\r
- if (CheckSum != 0) {\r
- return FALSE;\r
- }\r
-\r
- ValidNumber = 0;\r
- gBS->SetMem (ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING), 0);\r
-\r
- if ((EdidDataBlock->EstablishedTimings[0] != 0) ||\r
- (EdidDataBlock->EstablishedTimings[1] != 0) ||\r
- (EdidDataBlock->EstablishedTimings[2] != 0)\r
- ) {\r
- //\r
- // Established timing data\r
- //\r
- TimingBits = EdidDataBlock->EstablishedTimings[0] |\r
- (EdidDataBlock->EstablishedTimings[1] << 8) |\r
- ((EdidDataBlock->EstablishedTimings[2] & 0x80) << 9) ;\r
- for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER; Index ++) {\r
- if ((TimingBits & 0x1) != 0) {\r
- DEBUG ((EFI_D_INFO, "Established Timing: %d x %d\n",\r
- mEstablishedEdidTiming[Index].HorizontalResolution, mEstablishedEdidTiming[Index].VerticalResolution));\r
- ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&mEstablishedEdidTiming[Index]);\r
- ValidNumber ++;\r
- }\r
- TimingBits = TimingBits >> 1;\r
- }\r
- }\r
-\r
- //\r
- // Parse the standard timing data\r
- //\r
- BufferIndex = &EdidDataBlock->StandardTimingIdentification[0];\r
- for (Index = 0; Index < 8; Index ++) {\r
- //\r
- // Check if this is a valid Standard Timing entry\r
- // VESA documents unused fields should be set to 01h\r
- //\r
- if ((BufferIndex[0] != 0x1) && (BufferIndex[1] != 0x1)){\r
- //\r
- // A valid Standard Timing\r
- //\r
- HorizontalResolution = (UINT16) (BufferIndex[0] * 8 + 248);\r
- AspectRatio = (UINT8) (BufferIndex[1] >> 6);\r
- switch (AspectRatio) {\r
- case 0:\r
- VerticalResolution = (UINT16) (HorizontalResolution / 16 * 10);\r
- break;\r
- case 1:\r
- VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);\r
- break;\r
- case 2:\r
- VerticalResolution = (UINT16) (HorizontalResolution / 5 * 4);\r
- break;\r
- case 3:\r
- VerticalResolution = (UINT16) (HorizontalResolution / 16 * 9);\r
- break;\r
- default:\r
- VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);\r
- break;\r
- }\r
- RefreshRate = (UINT8) ((BufferIndex[1] & 0x1f) + 60);\r
- DEBUG ((EFI_D_INFO, "Standard Timing: %d x %d\n", HorizontalResolution, VerticalResolution));\r
- TempTiming.HorizontalResolution = HorizontalResolution;\r
- TempTiming.VerticalResolution = VerticalResolution;\r
- TempTiming.RefreshRate = RefreshRate;\r
- ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming);\r
- ValidNumber ++;\r
- }\r
- BufferIndex += 2;\r
- }\r
-\r
- //\r
- // Parse the Detailed Timing data\r
- //\r
- BufferIndex = &EdidDataBlock->DetailedTimingDescriptions[0];\r
- for (Index = 0; Index < 4; Index ++, BufferIndex += VESA_BIOS_EXTENSIONS_DETAILED_TIMING_EACH_DESCRIPTOR_SIZE) {\r
- if ((BufferIndex[0] == 0x0) && (BufferIndex[1] == 0x0)) {\r
- //\r
- // Check if this is a valid Detailed Timing Descriptor\r
- // If first 2 bytes are zero, it is monitor descriptor other than detailed timing descriptor\r
- //\r
- continue;\r
- }\r
- //\r
- // Calculate Horizontal and Vertical resolution\r
- //\r
- TempTiming.HorizontalResolution = ((UINT16)(BufferIndex[4] & 0xF0) << 4) | (BufferIndex[2]);\r
- TempTiming.VerticalResolution = ((UINT16)(BufferIndex[7] & 0xF0) << 4) | (BufferIndex[5]);\r
- DEBUG ((EFI_D_INFO, "Detailed Timing %d: %d x %d\n",\r
- Index, TempTiming.HorizontalResolution, TempTiming.VerticalResolution));\r
- ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming);\r
- ValidNumber ++;\r
- }\r
-\r
- ValidEdidTiming->ValidNumber = ValidNumber;\r
- return TRUE;\r
-}\r
-\r
-\r
-/**\r
- Search a specified Timing in all the valid EDID timings.\r
-\r
- @param ValidEdidTiming All valid EDID timing information.\r
- @param EdidTiming The Timing to search for.\r
-\r
- @retval TRUE Found.\r
- @retval FALSE Not found.\r
-\r
-**/\r
-BOOLEAN\r
-SearchEdidTiming (\r
- VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming,\r
- VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming\r
- )\r
-{\r
- UINT32 Index;\r
- UINT32 Key;\r
-\r
- Key = CalculateEdidKey (EdidTiming);\r
-\r
- for (Index = 0; Index < ValidEdidTiming->ValidNumber; Index ++) {\r
- if (Key == ValidEdidTiming->Key[Index]) {\r
- return TRUE;\r
- }\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-/**\r
- Check if all video child handles have been uninstalled.\r
-\r
- @param Controller Video controller handle\r
-\r
- @return TRUE Child handles exist.\r
- @return FALSE All video child handles have been uninstalled.\r
-\r
-**/\r
-BOOLEAN\r
-HasChildHandle (\r
- IN EFI_HANDLE Controller\r
- )\r
-{\r
- UINTN Index;\r
- EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
- UINTN EntryCount;\r
- BOOLEAN HasChild;\r
-\r
- EntryCount = 0;\r
- HasChild = FALSE;\r
- gBS->OpenProtocolInformation (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- &OpenInfoBuffer,\r
- &EntryCount\r
- );\r
- for (Index = 0; Index < EntryCount; Index++) {\r
- if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
- HasChild = TRUE;\r
- }\r
- }\r
-\r
- return HasChild;\r
-}\r
-\r
-/**\r
- Check for VBE device.\r
-\r
- @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure\r
-\r
- @retval EFI_SUCCESS VBE device found\r
-\r
-**/\r
-EFI_STATUS\r
-BiosVideoCheckForVbe (\r
- IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_IA32_REGISTER_SET Regs;\r
- UINT16 *ModeNumberPtr;\r
- UINT16 VbeModeNumber;\r
- BOOLEAN ModeFound;\r
- BOOLEAN EdidFound;\r
- BIOS_VIDEO_MODE_DATA *ModeBuffer;\r
- BIOS_VIDEO_MODE_DATA *CurrentModeData;\r
- UINTN PreferMode;\r
- UINTN ModeNumber;\r
- VESA_BIOS_EXTENSIONS_EDID_TIMING Timing;\r
- VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING ValidEdidTiming;\r
- EFI_EDID_OVERRIDE_PROTOCOL *EdidOverride;\r
- UINT32 EdidAttributes;\r
- BOOLEAN EdidOverrideFound;\r
- UINTN EdidOverrideDataSize;\r
- UINT8 *EdidOverrideDataBlock;\r
- UINTN EdidActiveDataSize;\r
- UINT8 *EdidActiveDataBlock;\r
- UINT32 HighestHorizontalResolution;\r
- UINT32 HighestVerticalResolution;\r
- UINTN HighestResolutionMode;\r
-\r
- EdidFound = TRUE;\r
- EdidOverrideFound = FALSE;\r
- EdidOverrideDataBlock = NULL;\r
- EdidActiveDataSize = 0;\r
- EdidActiveDataBlock = NULL;\r
- HighestHorizontalResolution = 0;\r
- HighestVerticalResolution = 0;\r
- HighestResolutionMode = 0;\r
-\r
- //\r
- // Allocate buffer under 1MB for VBE data structures\r
- //\r
- BiosVideoPrivate->NumberOfPagesBelow1MB = EFI_SIZE_TO_PAGES (\r
- sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK) +\r
- sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK) +\r
- sizeof (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK) +\r
- sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK)\r
- );\r
-\r
- BiosVideoPrivate->PagesBelow1MB = 0x00100000 - 1;\r
-\r
- Status = gBS->AllocatePages (\r
- AllocateMaxAddress,\r
- EfiBootServicesData,\r
- BiosVideoPrivate->NumberOfPagesBelow1MB,\r
- &BiosVideoPrivate->PagesBelow1MB\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- ZeroMem (&ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING));\r
-\r
- //\r
- // Fill in the VBE related data structures\r
- //\r
- BiosVideoPrivate->VbeInformationBlock = (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *) (UINTN) (BiosVideoPrivate->PagesBelow1MB);\r
- BiosVideoPrivate->VbeModeInformationBlock = (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeInformationBlock + 1);\r
- BiosVideoPrivate->VbeEdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) (BiosVideoPrivate->VbeModeInformationBlock + 1);\r
- BiosVideoPrivate->VbeCrtcInformationBlock = (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeEdidDataBlock + 1);\r
- BiosVideoPrivate->VbeSaveRestorePages = 0;\r
- BiosVideoPrivate->VbeSaveRestoreBuffer = 0;\r
-\r
- //\r
- // Test to see if the Video Adapter is compliant with VBE 3.0\r
- //\r
- gBS->SetMem (&Regs, sizeof (Regs), 0);\r
- Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION;\r
- gBS->SetMem (BiosVideoPrivate->VbeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK), 0);\r
- BiosVideoPrivate->VbeInformationBlock->VESASignature = VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE;\r
- Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeInformationBlock);\r
- Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeInformationBlock);\r
-\r
- BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
-\r
- Status = EFI_DEVICE_ERROR;\r
-\r
- //\r
- // See if the VESA call succeeded\r
- //\r
- if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
- return Status;\r
- }\r
- //\r
- // Check for 'VESA' signature\r
- //\r
- if (BiosVideoPrivate->VbeInformationBlock->VESASignature != VESA_BIOS_EXTENSIONS_VESA_SIGNATURE) {\r
- return Status;\r
- }\r
- //\r
- // Check to see if this is VBE 2.0 or higher\r
- //\r
- if (BiosVideoPrivate->VbeInformationBlock->VESAVersion < VESA_BIOS_EXTENSIONS_VERSION_2_0) {\r
- return Status;\r
- }\r
-\r
- EdidFound = FALSE;\r
- EdidAttributes = 0xff;\r
- EdidOverrideDataSize = 0;\r
-\r
- //\r
- // Find EDID Override protocol firstly, this protocol is installed by platform if needed.\r
- //\r
- Status = gBS->LocateProtocol (\r
- &gEfiEdidOverrideProtocolGuid,\r
- NULL,\r
- (VOID **) &EdidOverride\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Allocate double size of VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE to avoid overflow\r
- //\r
- EdidOverrideDataBlock = AllocatePool (VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE * 2);\r
- if (NULL == EdidOverrideDataBlock) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
- }\r
-\r
- Status = EdidOverride->GetEdid (\r
- EdidOverride,\r
- BiosVideoPrivate->Handle,\r
- &EdidAttributes,\r
- &EdidOverrideDataSize,\r
- (UINT8 **) &EdidOverrideDataBlock\r
- );\r
- if (!EFI_ERROR (Status) &&\r
- EdidAttributes == 0 &&\r
- EdidOverrideDataSize != 0) {\r
- //\r
- // Succeeded to get EDID Override Data\r
- //\r
- EdidOverrideFound = TRUE;\r
- }\r
- }\r
-\r
- if (!EdidOverrideFound || EdidAttributes == EFI_EDID_OVERRIDE_DONT_OVERRIDE) {\r
- //\r
- // If EDID Override data doesn't exist or EFI_EDID_OVERRIDE_DONT_OVERRIDE returned,\r
- // read EDID information through INT10 call\r
- //\r
-\r
- gBS->SetMem (&Regs, sizeof (Regs), 0);\r
- Regs.X.AX = VESA_BIOS_EXTENSIONS_EDID;\r
- Regs.X.BX = 1;\r
- Regs.X.CX = 0;\r
- Regs.X.DX = 0;\r
- Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);\r
- Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);\r
-\r
- BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
- //\r
- // See if the VESA call succeeded\r
- //\r
- if (Regs.X.AX == VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
- //\r
- // Set EDID Discovered Data\r
- //\r
- BiosVideoPrivate->EdidDiscovered.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;\r
- BiosVideoPrivate->EdidDiscovered.Edid = (UINT8 *) AllocateCopyPool (\r
- VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,\r
- BiosVideoPrivate->VbeEdidDataBlock\r
- );\r
-\r
- if (NULL == BiosVideoPrivate->EdidDiscovered.Edid) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
- }\r
-\r
- EdidFound = TRUE;\r
- }\r
- }\r
-\r
- if (EdidFound) {\r
- EdidActiveDataSize = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;\r
- EdidActiveDataBlock = BiosVideoPrivate->EdidDiscovered.Edid;\r
- } else if (EdidOverrideFound) {\r
- EdidActiveDataSize = EdidOverrideDataSize;\r
- EdidActiveDataBlock = EdidOverrideDataBlock;\r
- EdidFound = TRUE;\r
- }\r
-\r
- if (EdidFound) {\r
- //\r
- // Parse EDID data structure to retrieve modes supported by monitor\r
- //\r
- if (ParseEdidData ((UINT8 *) EdidActiveDataBlock, &ValidEdidTiming)) {\r
- //\r
- // Copy EDID Override Data to EDID Active Data\r
- //\r
- BiosVideoPrivate->EdidActive.SizeOfEdid = (UINT32) EdidActiveDataSize;\r
- BiosVideoPrivate->EdidActive.Edid = (UINT8 *) AllocateCopyPool (\r
- EdidActiveDataSize,\r
- EdidActiveDataBlock\r
- );\r
- if (NULL == BiosVideoPrivate->EdidActive.Edid) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
- }\r
- }\r
- } else {\r
- BiosVideoPrivate->EdidActive.SizeOfEdid = 0;\r
- BiosVideoPrivate->EdidActive.Edid = NULL;\r
- EdidFound = FALSE;\r
- }\r
-\r
- //\r
- // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode\r
- //\r
- ModeNumberPtr = (UINT16 *)\r
- (\r
- (((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xffff0000) >> 12) |\r
- ((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0000ffff)\r
- );\r
-\r
- PreferMode = 0;\r
- ModeNumber = 0;\r
-\r
- //\r
- // ModeNumberPtr may be not 16-byte aligned, so ReadUnaligned16 is used to access the buffer pointed by ModeNumberPtr.\r
- //\r
- for (VbeModeNumber = ReadUnaligned16 (ModeNumberPtr);\r
- VbeModeNumber != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST;\r
- VbeModeNumber = ReadUnaligned16 (++ModeNumberPtr)) {\r
- //\r
- // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number.\r
- //\r
- if ((VbeModeNumber & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) {\r
- continue;\r
- }\r
- //\r
- // Get the information about the mode\r
- //\r
- gBS->SetMem (&Regs, sizeof (Regs), 0);\r
- Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION;\r
- Regs.X.CX = VbeModeNumber;\r
- gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0);\r
- Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
- Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
-\r
- BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
-\r
- //\r
- // See if the call succeeded. If it didn't, then try the next mode.\r
- //\r
- if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
- continue;\r
- }\r
- //\r
- // See if the mode supports color. If it doesn't then try the next mode.\r
- //\r
- if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) == 0) {\r
- continue;\r
- }\r
- //\r
- // See if the mode supports graphics. If it doesn't then try the next mode.\r
- //\r
- if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS) == 0) {\r
- continue;\r
- }\r
- //\r
- // See if the mode supports a linear frame buffer. If it doesn't then try the next mode.\r
- //\r
- if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER) == 0) {\r
- continue;\r
- }\r
- //\r
- // See if the mode supports 32 bit color. If it doesn't then try the next mode.\r
- // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the\r
- // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel\r
- //\r
- if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) {\r
- continue;\r
- }\r
-\r
- if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) {\r
- continue;\r
- }\r
-\r
- if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) != 0) {\r
- continue;\r
- }\r
- //\r
- // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode.\r
- //\r
- if (BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr == 0) {\r
- continue;\r
- }\r
-\r
- DEBUG ((EFI_D_INFO, "Video Controller Mode 0x%x: %d x %d\n",\r
- VbeModeNumber, BiosVideoPrivate->VbeModeInformationBlock->XResolution, BiosVideoPrivate->VbeModeInformationBlock->YResolution));\r
-\r
- if (EdidFound && (ValidEdidTiming.ValidNumber > 0)) {\r
- //\r
- // EDID exist, check whether this mode match with any mode in EDID\r
- //\r
- Timing.HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
- Timing.VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
- if (!SearchEdidTiming (&ValidEdidTiming, &Timing)) {\r
- //\r
- // When EDID comes from INT10 call, EDID does not include 800x600, 640x480 and 1024x768,\r
- // but INT10 can support these modes, we add them into GOP mode.\r
- //\r
- if ((BiosVideoPrivate->EdidDiscovered.SizeOfEdid != 0) &&\r
- !((Timing.HorizontalResolution) == 1024 && (Timing.VerticalResolution == 768)) &&\r
- !((Timing.HorizontalResolution) == 800 && (Timing.VerticalResolution == 600)) &&\r
- !((Timing.HorizontalResolution) == 640 && (Timing.VerticalResolution == 480))) {\r
- continue;\r
- }\r
- }\r
- }\r
-\r
- //\r
- // Select a reasonable mode to be set for current display mode\r
- //\r
- ModeFound = FALSE;\r
-\r
- if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 1024 &&\r
- BiosVideoPrivate->VbeModeInformationBlock->YResolution == 768\r
- ) {\r
- ModeFound = TRUE;\r
- }\r
- if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 800 &&\r
- BiosVideoPrivate->VbeModeInformationBlock->YResolution == 600\r
- ) {\r
- ModeFound = TRUE;\r
- PreferMode = ModeNumber;\r
- }\r
- if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 640 &&\r
- BiosVideoPrivate->VbeModeInformationBlock->YResolution == 480\r
- ) {\r
- ModeFound = TRUE;\r
- }\r
-\r
- if ((!EdidFound) && (!ModeFound)) {\r
- //\r
- // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480\r
- //\r
- continue;\r
- }\r
-\r
- //\r
- // Record the highest resolution mode to set later\r
- //\r
- if ((BiosVideoPrivate->VbeModeInformationBlock->XResolution > HighestHorizontalResolution) ||\r
- ((BiosVideoPrivate->VbeModeInformationBlock->XResolution == HighestHorizontalResolution) &&\r
- (BiosVideoPrivate->VbeModeInformationBlock->YResolution > HighestVerticalResolution))) {\r
- HighestHorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
- HighestVerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
- HighestResolutionMode = ModeNumber;\r
- }\r
-\r
- //\r
- // Add mode to the list of available modes\r
- //\r
- ModeNumber ++;\r
- ModeBuffer = (BIOS_VIDEO_MODE_DATA *) AllocatePool (\r
- ModeNumber * sizeof (BIOS_VIDEO_MODE_DATA)\r
- );\r
- if (NULL == ModeBuffer) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
- }\r
-\r
- if (ModeNumber > 1) {\r
- CopyMem (\r
- ModeBuffer,\r
- BiosVideoPrivate->ModeData,\r
- (ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA)\r
- );\r
- }\r
-\r
- if (BiosVideoPrivate->ModeData != NULL) {\r
- FreePool (BiosVideoPrivate->ModeData);\r
- }\r
-\r
- CurrentModeData = &ModeBuffer[ModeNumber - 1];\r
- CurrentModeData->VbeModeNumber = VbeModeNumber;\r
- if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) {\r
- CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine;\r
- CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition;\r
- CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRedMaskSize) - 1);\r
- CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->LinBlueFieldPosition;\r
- CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinBlueMaskSize) - 1);\r
- CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->LinGreenFieldPosition;\r
- CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinGreenMaskSize) - 1);\r
- CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRsvdFieldPosition;\r
- CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRsvdMaskSize) - 1);\r
- } else {\r
- CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->BytesPerScanLine;\r
- CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->RedFieldPosition;\r
- CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RedMaskSize) - 1);\r
- CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->BlueFieldPosition;\r
- CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->BlueMaskSize) - 1);\r
- CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->GreenFieldPosition;\r
- CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->GreenMaskSize) - 1);\r
- CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->RsvdFieldPosition;\r
- CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RsvdMaskSize) - 1);\r
- }\r
-\r
- CurrentModeData->PixelFormat = PixelBitMask;\r
- if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel == 32) &&\r
- (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {\r
- if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {\r
- CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;\r
- } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {\r
- CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;\r
- }\r
- }\r
-\r
- CurrentModeData->PixelBitMask.RedMask = ((UINT32) CurrentModeData->Red.Mask) << CurrentModeData->Red.Position;\r
- CurrentModeData->PixelBitMask.GreenMask = ((UINT32) CurrentModeData->Green.Mask) << CurrentModeData->Green.Position;\r
- CurrentModeData->PixelBitMask.BlueMask = ((UINT32) CurrentModeData->Blue.Mask) << CurrentModeData->Blue.Position;\r
- CurrentModeData->PixelBitMask.ReservedMask = ((UINT32) CurrentModeData->Reserved.Mask) << CurrentModeData->Reserved.Position;\r
-\r
- CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr;\r
- CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
- CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
-\r
- CurrentModeData->BitsPerPixel = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel;\r
- CurrentModeData->FrameBufferSize = CurrentModeData->BytesPerScanLine * CurrentModeData->VerticalResolution;\r
- //\r
- // Make sure the FrameBufferSize does not exceed the max available frame buffer size reported by VEB.\r
- //\r
- ASSERT (CurrentModeData->FrameBufferSize <= ((UINT32)BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024));\r
-\r
- BiosVideoPrivate->ModeData = ModeBuffer;\r
- }\r
- //\r
- // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT\r
- //\r
- if (ModeNumber == 0) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto Done;\r
- }\r
-\r
- //\r
- // Assign Gop's Blt function\r
- //\r
- BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVbeBlt;\r
-\r
- BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = (UINT32) ModeNumber;\r
- //\r
- // Current mode is unknow till now, set it to an invalid mode.\r
- //\r
- BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
-\r
- //\r
- // Find the best mode to initialize\r
- //\r
- if ((PcdGet32 (PcdVideoHorizontalResolution) == 0x0) || (PcdGet32 (PcdVideoVerticalResolution) == 0x0)) {\r
- DEBUG_CODE (\r
- BIOS_VIDEO_MODE_DATA *ModeData;\r
- ModeData = &BiosVideoPrivate->ModeData[HighestResolutionMode];\r
- DEBUG ((EFI_D_INFO, "BiosVideo set highest resolution %d x %d\n",\r
- ModeData->HorizontalResolution, ModeData->VerticalResolution));\r
- );\r
- PreferMode = HighestResolutionMode;\r
- }\r
- Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, (UINT32) PreferMode);\r
- if (EFI_ERROR (Status)) {\r
- for (PreferMode = 0; PreferMode < ModeNumber; PreferMode ++) {\r
- Status = BiosVideoGraphicsOutputSetMode (\r
- &BiosVideoPrivate->GraphicsOutput,\r
- (UINT32) PreferMode\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- break;\r
- }\r
- }\r
- if (PreferMode == ModeNumber) {\r
- //\r
- // None mode is set successfully.\r
- //\r
- goto Done;\r
- }\r
- }\r
-\r
-Done:\r
- //\r
- // If there was an error, then free the mode structure\r
- //\r
- if (EFI_ERROR (Status)) {\r
- if (BiosVideoPrivate->ModeData != NULL) {\r
- FreePool (BiosVideoPrivate->ModeData);\r
- BiosVideoPrivate->ModeData = NULL;\r
- BiosVideoPrivate->MaxMode = 0;\r
- }\r
- if (EdidOverrideDataBlock != NULL) {\r
- FreePool (EdidOverrideDataBlock);\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Check for VGA device.\r
-\r
- @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure\r
-\r
- @retval EFI_SUCCESS Standard VGA device found\r
-\r
-**/\r
-EFI_STATUS\r
-BiosVideoCheckForVga (\r
- IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BIOS_VIDEO_MODE_DATA *ModeBuffer;\r
-\r
- Status = EFI_UNSUPPORTED;\r
-\r
- //\r
- // Assign Gop's Blt function\r
- //\r
- BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVgaBlt;\r
-\r
- //\r
- // Add mode to the list of available modes\r
- // caller should guarantee that Mode has been allocated.\r
- //\r
- ASSERT (BiosVideoPrivate->GraphicsOutput.Mode != NULL);\r
- BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = 1;\r
-\r
- ModeBuffer = (BIOS_VIDEO_MODE_DATA *) AllocatePool (\r
- sizeof (BIOS_VIDEO_MODE_DATA)\r
- );\r
- if (NULL == ModeBuffer) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
- }\r
-\r
- ModeBuffer->VbeModeNumber = 0x0012;\r
- ModeBuffer->BytesPerScanLine = 640;\r
- ModeBuffer->LinearFrameBuffer = (VOID *) (UINTN) (0xa0000);\r
- ModeBuffer->HorizontalResolution = 640;\r
- ModeBuffer->VerticalResolution = 480;\r
- ModeBuffer->PixelFormat = PixelBltOnly;\r
- ModeBuffer->BitsPerPixel = 8;\r
- ModeBuffer->ColorDepth = 32;\r
- ModeBuffer->RefreshRate = 60;\r
-\r
- BiosVideoPrivate->ModeData = ModeBuffer;\r
-\r
- //\r
- // Test to see if the Video Adapter support the 640x480 16 color mode\r
- //\r
- BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
- Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, 0);\r
-\r
-Done:\r
- //\r
- // If there was an error, then free the mode structure\r
- //\r
- if (EFI_ERROR (Status)) {\r
- if (BiosVideoPrivate->ModeData != NULL) {\r
- FreePool (BiosVideoPrivate->ModeData);\r
- BiosVideoPrivate->ModeData = NULL;\r
- }\r
- if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
- if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
- FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
- BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL;\r
- }\r
- FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
- BiosVideoPrivate->GraphicsOutput.Mode = NULL;\r
- }\r
- }\r
- return Status;\r
-}\r
-\r
-//\r
-// Graphics Output Protocol Member Functions for VESA BIOS Extensions\r
-//\r
-\r
-/**\r
- Graphics Output protocol interface to get video mode.\r
-\r
- @param This Protocol instance pointer.\r
- @param ModeNumber The mode number to return information on.\r
- @param SizeOfInfo A pointer to the size, in bytes, of the Info\r
- buffer.\r
- @param Info Caller allocated buffer that returns information\r
- about ModeNumber.\r
-\r
- @retval EFI_SUCCESS Mode information returned.\r
- @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the\r
- video mode.\r
- @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()\r
- @retval EFI_INVALID_PARAMETER One of the input args was NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BiosVideoGraphicsOutputQueryMode (\r
- IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
- IN UINT32 ModeNumber,\r
- OUT UINTN *SizeOfInfo,\r
- OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
- )\r
-{\r
- BIOS_VIDEO_DEV *BiosVideoPrivate;\r
- BIOS_VIDEO_MODE_DATA *ModeData;\r
-\r
- BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
-\r
- if (BiosVideoPrivate->HardwareNeedsStarting) {\r
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
- EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
- EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR,\r
- BiosVideoPrivate->GopDevicePath\r
- );\r
- return EFI_NOT_STARTED;\r
- }\r
-\r
- if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- *Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (\r
- sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)\r
- );\r
- if (NULL == *Info) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
-\r
- ModeData = &BiosVideoPrivate->ModeData[ModeNumber];\r
- (*Info)->Version = 0;\r
- (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
- (*Info)->VerticalResolution = ModeData->VerticalResolution;\r
- (*Info)->PixelFormat = ModeData->PixelFormat;\r
- CopyMem (&((*Info)->PixelInformation), &(ModeData->PixelBitMask), sizeof(ModeData->PixelBitMask));\r
-\r
- (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Worker function to set video mode.\r
-\r
- @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV.\r
- @param ModeData The mode data to be set.\r
- @param DevicePath Pointer to Device Path Protocol.\r
-\r
- @retval EFI_SUCCESS Graphics mode was changed.\r
- @retval EFI_DEVICE_ERROR The device had an error and could not complete the\r
- request.\r
- @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.\r
-\r
-**/\r
-EFI_STATUS\r
-BiosVideoSetModeWorker (\r
- IN BIOS_VIDEO_DEV *BiosVideoPrivate,\r
- IN BIOS_VIDEO_MODE_DATA *ModeData,\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_IA32_REGISTER_SET Regs;\r
-\r
- if (BiosVideoPrivate->LineBuffer != NULL) {\r
- FreePool (BiosVideoPrivate->LineBuffer);\r
- }\r
-\r
- if (BiosVideoPrivate->VgaFrameBuffer != NULL) {\r
- FreePool (BiosVideoPrivate->VgaFrameBuffer);\r
- }\r
-\r
- if (BiosVideoPrivate->VbeFrameBuffer != NULL) {\r
- FreePool (BiosVideoPrivate->VbeFrameBuffer);\r
- }\r
-\r
- BiosVideoPrivate->LineBuffer = (UINT8 *) AllocatePool (\r
- ModeData->BytesPerScanLine\r
- );\r
- if (NULL == BiosVideoPrivate->LineBuffer) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- //\r
- // Clear all registers\r
- //\r
- ZeroMem (&Regs, sizeof (Regs));\r
-\r
- if (ModeData->VbeModeNumber < 0x100) {\r
- //\r
- // Allocate a working buffer for BLT operations to the VGA frame buffer\r
- //\r
- BiosVideoPrivate->VgaFrameBuffer = (UINT8 *) AllocatePool (4 * 480 * 80);\r
- if (NULL == BiosVideoPrivate->VgaFrameBuffer) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- //\r
- // Set VGA Mode\r
- //\r
- Regs.X.AX = ModeData->VbeModeNumber;\r
- BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
-\r
- } else {\r
- //\r
- // Allocate a working buffer for BLT operations to the VBE frame buffer\r
- //\r
- BiosVideoPrivate->VbeFrameBuffer =\r
- (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool (\r
- ModeData->BytesPerScanLine * ModeData->VerticalResolution\r
- );\r
- if (NULL == BiosVideoPrivate->VbeFrameBuffer) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- //\r
- // Set VBE mode\r
- //\r
- Regs.X.AX = VESA_BIOS_EXTENSIONS_SET_MODE;\r
- Regs.X.BX = (UINT16) (ModeData->VbeModeNumber | VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER);\r
- ZeroMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK));\r
- Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);\r
- Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);\r
- BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
-\r
- //\r
- // Check to see if the call succeeded\r
- //\r
- if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
- EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
- EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR,\r
- DevicePath\r
- );\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // Initialize the state of the VbeFrameBuffer\r
- //\r
- Status = BiosVideoPrivate->PciIo->Mem.Read (\r
- BiosVideoPrivate->PciIo,\r
- EfiPciIoWidthUint32,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- (UINT64) (UINTN) ModeData->LinearFrameBuffer,\r
- (ModeData->BytesPerScanLine * ModeData->VerticalResolution) >> 2,\r
- BiosVideoPrivate->VbeFrameBuffer\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Graphics Output protocol interface to set video mode.\r
-\r
- @param This Protocol instance pointer.\r
- @param ModeNumber The mode number to be set.\r
-\r
- @retval EFI_SUCCESS Graphics mode was changed.\r
- @retval EFI_DEVICE_ERROR The device had an error and could not complete the\r
- request.\r
- @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BiosVideoGraphicsOutputSetMode (\r
- IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,\r
- IN UINT32 ModeNumber\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BIOS_VIDEO_DEV *BiosVideoPrivate;\r
- BIOS_VIDEO_MODE_DATA *ModeData;\r
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
-\r
- if (This == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
-\r
- ModeData = &BiosVideoPrivate->ModeData[ModeNumber];\r
-\r
- if (ModeNumber >= This->Mode->MaxMode) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- if (ModeNumber == This->Mode->Mode) {\r
- //\r
- // Clear screen to black\r
- //\r
- ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
- BiosVideoGraphicsOutputVbeBlt (\r
- This,\r
- &Background,\r
- EfiBltVideoFill,\r
- 0,\r
- 0,\r
- 0,\r
- 0,\r
- ModeData->HorizontalResolution,\r
- ModeData->VerticalResolution,\r
- 0\r
- );\r
- return EFI_SUCCESS;\r
- }\r
-\r
- Status = BiosVideoSetModeWorker (BiosVideoPrivate, ModeData, BiosVideoPrivate->GopDevicePath);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- This->Mode->Mode = ModeNumber;\r
- This->Mode->Info->Version = 0;\r
- This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
- This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
- This->Mode->Info->PixelFormat = ModeData->PixelFormat;\r
- CopyMem (&(This->Mode->Info->PixelInformation), &(ModeData->PixelBitMask), sizeof (ModeData->PixelBitMask));\r
- This->Mode->Info->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
- This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
- This->Mode->FrameBufferSize = ModeData->FrameBufferSize;\r
- This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) ModeData->LinearFrameBuffer;\r
-\r
- BiosVideoPrivate->HardwareNeedsStarting = FALSE;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.\r
-\r
- @param PciIo The pointer of EFI_PCI_IO_PROTOCOL\r
- @param VbeBuffer The data to transfer to screen\r
- @param MemAddress Physical frame buffer base address\r
- @param DestinationX The X coordinate of the destination for BltOperation\r
- @param DestinationY The Y coordinate of the destination for BltOperation\r
- @param TotalBytes The total bytes of copy\r
- @param VbePixelWidth Bytes per pixel\r
- @param BytesPerScanLine Bytes per scan line\r
-\r
-**/\r
-VOID\r
-CopyVideoBuffer (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT8 *VbeBuffer,\r
- IN VOID *MemAddress,\r
- IN UINTN DestinationX,\r
- IN UINTN DestinationY,\r
- IN UINTN TotalBytes,\r
- IN UINT32 VbePixelWidth,\r
- IN UINTN BytesPerScanLine\r
- )\r
-{\r
- UINTN FrameBufferAddr;\r
- UINTN CopyBlockNum;\r
- UINTN RemainingBytes;\r
- UINTN UnalignedBytes;\r
- EFI_STATUS Status;\r
-\r
- FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth;\r
-\r
- //\r
- // If TotalBytes is less than 4 bytes, only start byte copy.\r
- //\r
- if (TotalBytes < 4) {\r
- Status = PciIo->Mem.Write (\r
- PciIo,\r
- EfiPciIoWidthUint8,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- (UINT64) FrameBufferAddr,\r
- TotalBytes,\r
- VbeBuffer\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- return;\r
- }\r
-\r
- //\r
- // If VbeBuffer is not 4-byte aligned, start byte copy.\r
- //\r
- UnalignedBytes = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3;\r
-\r
- if (UnalignedBytes != 0) {\r
- Status = PciIo->Mem.Write (\r
- PciIo,\r
- EfiPciIoWidthUint8,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- (UINT64) FrameBufferAddr,\r
- UnalignedBytes,\r
- VbeBuffer\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- FrameBufferAddr += UnalignedBytes;\r
- VbeBuffer += UnalignedBytes;\r
- }\r
-\r
- //\r
- // Calculate 4-byte block count and remaining bytes.\r
- //\r
- CopyBlockNum = (TotalBytes - UnalignedBytes) >> 2;\r
- RemainingBytes = (TotalBytes - UnalignedBytes) & 3;\r
-\r
- //\r
- // Copy 4-byte block and remaining bytes to physical frame buffer.\r
- //\r
- if (CopyBlockNum != 0) {\r
- Status = PciIo->Mem.Write (\r
- PciIo,\r
- EfiPciIoWidthUint32,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- (UINT64) FrameBufferAddr,\r
- CopyBlockNum,\r
- VbeBuffer\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
-\r
- if (RemainingBytes != 0) {\r
- FrameBufferAddr += (CopyBlockNum << 2);\r
- VbeBuffer += (CopyBlockNum << 2);\r
- Status = PciIo->Mem.Write (\r
- PciIo,\r
- EfiPciIoWidthUint8,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- (UINT64) FrameBufferAddr,\r
- RemainingBytes,\r
- VbeBuffer\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
-}\r
-\r
-/**\r
- Worker function to block transfer for VBE device.\r
-\r
- @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV\r
- @param BltBuffer The data to transfer to screen\r
- @param BltOperation The operation to perform\r
- @param SourceX The X coordinate of the source for BltOperation\r
- @param SourceY The Y coordinate of the source for BltOperation\r
- @param DestinationX The X coordinate of the destination for\r
- BltOperation\r
- @param DestinationY The Y coordinate of the destination for\r
- BltOperation\r
- @param Width The width of a rectangle in the blt rectangle in\r
- pixels\r
- @param Height The height of a rectangle in the blt rectangle in\r
- pixels\r
- @param Delta Not used for EfiBltVideoFill and\r
- EfiBltVideoToVideo operation. If a Delta of 0 is\r
- used, the entire BltBuffer will be operated on. If\r
- a subrectangle of the BltBuffer is used, then\r
- Delta represents the number of bytes in a row of\r
- the BltBuffer.\r
- @param Mode Mode data.\r
-\r
- @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
- @retval EFI_SUCCESS Blt operation success\r
-\r
-**/\r
-EFI_STATUS\r
-BiosVideoVbeBltWorker (\r
- IN BIOS_VIDEO_DEV *BiosVideoPrivate,\r
- IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
- IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
- IN UINTN SourceX,\r
- IN UINTN SourceY,\r
- IN UINTN DestinationX,\r
- IN UINTN DestinationY,\r
- IN UINTN Width,\r
- IN UINTN Height,\r
- IN UINTN Delta,\r
- IN BIOS_VIDEO_MODE_DATA *Mode\r
- )\r
-{\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- EFI_TPL OriginalTPL;\r
- UINTN DstY;\r
- UINTN SrcY;\r
- UINTN DstX;\r
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
- VOID *MemAddress;\r
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;\r
- UINTN BytesPerScanLine;\r
- UINTN Index;\r
- UINT8 *VbeBuffer;\r
- UINT8 *VbeBuffer1;\r
- UINT8 *BltUint8;\r
- UINT32 VbePixelWidth;\r
- UINT32 Pixel;\r
- UINTN TotalBytes;\r
-\r
- PciIo = BiosVideoPrivate->PciIo;\r
-\r
- VbeFrameBuffer = BiosVideoPrivate->VbeFrameBuffer;\r
- MemAddress = Mode->LinearFrameBuffer;\r
- BytesPerScanLine = Mode->BytesPerScanLine;\r
- VbePixelWidth = Mode->BitsPerPixel / 8;\r
- BltUint8 = (UINT8 *) BltBuffer;\r
- TotalBytes = Width * VbePixelWidth;\r
-\r
- if (((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (Width == 0 || Height == 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // We need to fill the Virtual Screen buffer with the blt data.\r
- // The virtual screen is upside down, as the first row is the bootom row of\r
- // the image.\r
- //\r
- if (BltOperation == EfiBltVideoToBltBuffer) {\r
- //\r
- // Video to BltBuffer: Source is Video, destination is BltBuffer\r
- //\r
- if (SourceY + Height > Mode->VerticalResolution) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (SourceX + Width > Mode->HorizontalResolution) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- } else {\r
- //\r
- // BltBuffer to Video: Source is BltBuffer, destination is Video\r
- //\r
- if (DestinationY + Height > Mode->VerticalResolution) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (DestinationX + Width > Mode->HorizontalResolution) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
- //\r
- // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
- // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
- // the number of bytes in each row can be computed.\r
- //\r
- if (Delta == 0) {\r
- Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
- }\r
- //\r
- // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
- // We would not want a timer based event (Cursor, ...) to come in while we are\r
- // doing this operation.\r
- //\r
- OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
-\r
- switch (BltOperation) {\r
- case EfiBltVideoToBltBuffer:\r
- for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {\r
- Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
- //\r
- // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL\r
- //\r
- VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));\r
- for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
- Pixel = VbeBuffer[0] | VbeBuffer[1] << 8 | VbeBuffer[2] << 16 | VbeBuffer[3] << 24;\r
- Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);\r
- Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);\r
- Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);\r
- Blt->Reserved = 0;\r
- Blt++;\r
- VbeBuffer += VbePixelWidth;\r
- }\r
-\r
- }\r
- break;\r
-\r
- case EfiBltVideoToVideo:\r
- for (Index = 0; Index < Height; Index++) {\r
- if (DestinationY <= SourceY) {\r
- SrcY = SourceY + Index;\r
- DstY = DestinationY + Index;\r
- } else {\r
- SrcY = SourceY + Height - Index - 1;\r
- DstY = DestinationY + Height - Index - 1;\r
- }\r
-\r
- VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);\r
- VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);\r
-\r
- gBS->CopyMem (\r
- VbeBuffer,\r
- VbeBuffer1,\r
- TotalBytes\r
- );\r
-\r
- //\r
- // Update physical frame buffer.\r
- //\r
- CopyVideoBuffer (\r
- PciIo,\r
- VbeBuffer,\r
- MemAddress,\r
- DestinationX,\r
- DstY,\r
- TotalBytes,\r
- VbePixelWidth,\r
- BytesPerScanLine\r
- );\r
- }\r
- break;\r
-\r
- case EfiBltVideoFill:\r
- VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
- Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;\r
- //\r
- // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
- //\r
- Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
- (\r
- (Blt->Green & Mode->Green.Mask) <<\r
- Mode->Green.Position\r
- ) |\r
- ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
-\r
- for (Index = 0; Index < Width; Index++) {\r
- gBS->CopyMem (\r
- VbeBuffer,\r
- &Pixel,\r
- VbePixelWidth\r
- );\r
- VbeBuffer += VbePixelWidth;\r
- }\r
-\r
- VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
- for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {\r
- gBS->CopyMem (\r
- (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),\r
- VbeBuffer,\r
- TotalBytes\r
- );\r
- }\r
-\r
- for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {\r
- //\r
- // Update physical frame buffer.\r
- //\r
- CopyVideoBuffer (\r
- PciIo,\r
- VbeBuffer,\r
- MemAddress,\r
- DestinationX,\r
- DstY,\r
- TotalBytes,\r
- VbePixelWidth,\r
- BytesPerScanLine\r
- );\r
- }\r
- break;\r
-\r
- case EfiBltBufferToVideo:\r
- for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {\r
- Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
- VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
- for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
- //\r
- // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
- //\r
- Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
- ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |\r
- ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
- gBS->CopyMem (\r
- VbeBuffer,\r
- &Pixel,\r
- VbePixelWidth\r
- );\r
- Blt++;\r
- VbeBuffer += VbePixelWidth;\r
- }\r
-\r
- VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
-\r
- //\r
- // Update physical frame buffer.\r
- //\r
- CopyVideoBuffer (\r
- PciIo,\r
- VbeBuffer,\r
- MemAddress,\r
- DestinationX,\r
- DstY,\r
- TotalBytes,\r
- VbePixelWidth,\r
- BytesPerScanLine\r
- );\r
- }\r
- break;\r
-\r
- default: ;\r
- }\r
-\r
- gBS->RestoreTPL (OriginalTPL);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Graphics Output protocol instance to block transfer for VBE device.\r
-\r
- @param This Pointer to Graphics Output protocol instance\r
- @param BltBuffer The data to transfer to screen\r
- @param BltOperation The operation to perform\r
- @param SourceX The X coordinate of the source for BltOperation\r
- @param SourceY The Y coordinate of the source for BltOperation\r
- @param DestinationX The X coordinate of the destination for\r
- BltOperation\r
- @param DestinationY The Y coordinate of the destination for\r
- BltOperation\r
- @param Width The width of a rectangle in the blt rectangle in\r
- pixels\r
- @param Height The height of a rectangle in the blt rectangle in\r
- pixels\r
- @param Delta Not used for EfiBltVideoFill and\r
- EfiBltVideoToVideo operation. If a Delta of 0 is\r
- used, the entire BltBuffer will be operated on. If\r
- a subrectangle of the BltBuffer is used, then\r
- Delta represents the number of bytes in a row of\r
- the BltBuffer.\r
-\r
- @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
- @retval EFI_SUCCESS Blt operation success\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BiosVideoGraphicsOutputVbeBlt (\r
- IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
- IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
- IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
- IN UINTN SourceX,\r
- IN UINTN SourceY,\r
- IN UINTN DestinationX,\r
- IN UINTN DestinationY,\r
- IN UINTN Width,\r
- IN UINTN Height,\r
- IN UINTN Delta\r
- )\r
-{\r
- BIOS_VIDEO_DEV *BiosVideoPrivate;\r
- BIOS_VIDEO_MODE_DATA *Mode;\r
-\r
- if (This == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
- Mode = &BiosVideoPrivate->ModeData[This->Mode->Mode];\r
-\r
- return BiosVideoVbeBltWorker (\r
- BiosVideoPrivate,\r
- BltBuffer,\r
- BltOperation,\r
- SourceX,\r
- SourceY,\r
- DestinationX,\r
- DestinationY,\r
- Width,\r
- Height,\r
- Delta,\r
- Mode\r
- );\r
-}\r
-\r
-/**\r
- Write graphics controller registers.\r
-\r
- @param PciIo Pointer to PciIo protocol instance of the\r
- controller\r
- @param Address Register address\r
- @param Data Data to be written to register\r
-\r
- @return None\r
-\r
-**/\r
-VOID\r
-WriteGraphicsController (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINTN Address,\r
- IN UINTN Data\r
- )\r
-{\r
- Address = Address | (Data << 8);\r
- PciIo->Io.Write (\r
- PciIo,\r
- EfiPciIoWidthUint16,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER,\r
- 1,\r
- &Address\r
- );\r
-}\r
-\r
-\r
-/**\r
- Read the four bit plane of VGA frame buffer.\r
-\r
- @param PciIo Pointer to PciIo protocol instance of the\r
- controller\r
- @param HardwareBuffer Hardware VGA frame buffer address\r
- @param MemoryBuffer Memory buffer address\r
- @param WidthInBytes Number of bytes in a line to read\r
- @param Height Height of the area to read\r
-\r
- @return None\r
-\r
-**/\r
-VOID\r
-VgaReadBitPlanes (\r
- EFI_PCI_IO_PROTOCOL *PciIo,\r
- UINT8 *HardwareBuffer,\r
- UINT8 *MemoryBuffer,\r
- UINTN WidthInBytes,\r
- UINTN Height\r
- )\r
-{\r
- UINTN BitPlane;\r
- UINTN Rows;\r
- UINTN FrameBufferOffset;\r
- UINT8 *Source;\r
- UINT8 *Destination;\r
-\r
- //\r
- // Program the Mode Register Write mode 0, Read mode 0\r
- //\r
- WriteGraphicsController (\r
- PciIo,\r
- VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
- VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0\r
- );\r
-\r
- for (BitPlane = 0, FrameBufferOffset = 0;\r
- BitPlane < VGA_NUMBER_OF_BIT_PLANES;\r
- BitPlane++, FrameBufferOffset += VGA_BYTES_PER_BIT_PLANE\r
- ) {\r
- //\r
- // Program the Read Map Select Register to select the correct bit plane\r
- //\r
- WriteGraphicsController (\r
- PciIo,\r
- VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER,\r
- BitPlane\r
- );\r
-\r
- Source = HardwareBuffer;\r
- Destination = MemoryBuffer + FrameBufferOffset;\r
-\r
- for (Rows = 0; Rows < Height; Rows++, Source += VGA_BYTES_PER_SCAN_LINE, Destination += VGA_BYTES_PER_SCAN_LINE) {\r
- PciIo->Mem.Read (\r
- PciIo,\r
- EfiPciIoWidthUint8,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- (UINT64) (UINTN) Source,\r
- WidthInBytes,\r
- (VOID *) Destination\r
- );\r
- }\r
- }\r
-}\r
-\r
-\r
-/**\r
- Internal routine to convert VGA color to Grahpics Output color.\r
-\r
- @param MemoryBuffer Buffer containing VGA color\r
- @param CoordinateX The X coordinate of pixel on screen\r
- @param CoordinateY The Y coordinate of pixel on screen\r
- @param BltBuffer Buffer to contain converted Grahpics Output color\r
-\r
- @return None\r
-\r
-**/\r
-VOID\r
-VgaConvertToGraphicsOutputColor (\r
- UINT8 *MemoryBuffer,\r
- UINTN CoordinateX,\r
- UINTN CoordinateY,\r
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer\r
- )\r
-{\r
- UINTN Mask;\r
- UINTN Bit;\r
- UINTN Color;\r
-\r
- MemoryBuffer += ((CoordinateY << 6) + (CoordinateY << 4) + (CoordinateX >> 3));\r
- Mask = mVgaBitMaskTable[CoordinateX & 0x07];\r
- for (Bit = 0x01, Color = 0; Bit < 0x10; Bit <<= 1, MemoryBuffer += VGA_BYTES_PER_BIT_PLANE) {\r
- if ((*MemoryBuffer & Mask) != 0) {\r
- Color |= Bit;\r
- }\r
- }\r
-\r
- *BltBuffer = mVgaColorToGraphicsOutputColor[Color];\r
-}\r
-\r
-/**\r
- Internal routine to convert Grahpics Output color to VGA color.\r
-\r
- @param BltBuffer buffer containing Grahpics Output color\r
-\r
- @return Converted VGA color\r
-\r
-**/\r
-UINT8\r
-VgaConvertColor (\r
- IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer\r
- )\r
-{\r
- UINT8 Color;\r
-\r
- Color = (UINT8) ((BltBuffer->Blue >> 7) | ((BltBuffer->Green >> 6) & 0x02) | ((BltBuffer->Red >> 5) & 0x04));\r
- if ((BltBuffer->Red + BltBuffer->Green + BltBuffer->Blue) > 0x180) {\r
- Color |= 0x08;\r
- }\r
-\r
- return Color;\r
-}\r
-\r
-\r
-/**\r
- Grahpics Output protocol instance to block transfer for VGA device.\r
-\r
- @param This Pointer to Grahpics Output protocol instance\r
- @param BltBuffer The data to transfer to screen\r
- @param BltOperation The operation to perform\r
- @param SourceX The X coordinate of the source for BltOperation\r
- @param SourceY The Y coordinate of the source for BltOperation\r
- @param DestinationX The X coordinate of the destination for\r
- BltOperation\r
- @param DestinationY The Y coordinate of the destination for\r
- BltOperation\r
- @param Width The width of a rectangle in the blt rectangle in\r
- pixels\r
- @param Height The height of a rectangle in the blt rectangle in\r
- pixels\r
- @param Delta Not used for EfiBltVideoFill and\r
- EfiBltVideoToVideo operation. If a Delta of 0 is\r
- used, the entire BltBuffer will be operated on. If\r
- a subrectangle of the BltBuffer is used, then\r
- Delta represents the number of bytes in a row of\r
- the BltBuffer.\r
-\r
- @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
- @retval EFI_SUCCESS Blt operation success\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BiosVideoGraphicsOutputVgaBlt (\r
- IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
- IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
- IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
- IN UINTN SourceX,\r
- IN UINTN SourceY,\r
- IN UINTN DestinationX,\r
- IN UINTN DestinationY,\r
- IN UINTN Width,\r
- IN UINTN Height,\r
- IN UINTN Delta\r
- )\r
-{\r
- BIOS_VIDEO_DEV *BiosVideoPrivate;\r
- EFI_TPL OriginalTPL;\r
- UINT8 *MemAddress;\r
- UINTN BytesPerScanLine;\r
- UINTN Bit;\r
- UINTN Index;\r
- UINTN Index1;\r
- UINTN StartAddress;\r
- UINTN Bytes;\r
- UINTN Offset;\r
- UINT8 LeftMask;\r
- UINT8 RightMask;\r
- UINTN Address;\r
- UINTN AddressFix;\r
- UINT8 *Address1;\r
- UINT8 *SourceAddress;\r
- UINT8 *DestinationAddress;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- UINT8 Data;\r
- UINT8 PixelColor;\r
- UINT8 *VgaFrameBuffer;\r
- UINTN SourceOffset;\r
- UINTN SourceWidth;\r
- UINTN Rows;\r
- UINTN Columns;\r
- UINTN CoordinateX;\r
- UINTN CoordinateY;\r
- UINTN CurrentMode;\r
-\r
- if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
-\r
- CurrentMode = This->Mode->Mode;\r
- PciIo = BiosVideoPrivate->PciIo;\r
- MemAddress = BiosVideoPrivate->ModeData[CurrentMode].LinearFrameBuffer;\r
- BytesPerScanLine = BiosVideoPrivate->ModeData[CurrentMode].BytesPerScanLine >> 3;\r
- VgaFrameBuffer = BiosVideoPrivate->VgaFrameBuffer;\r
-\r
-\r
- if (Width == 0 || Height == 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // We need to fill the Virtual Screen buffer with the blt data.\r
- // The virtual screen is upside down, as the first row is the bootom row of\r
- // the image.\r
- //\r
- if (BltOperation == EfiBltVideoToBltBuffer) {\r
- //\r
- // Video to BltBuffer: Source is Video, destination is BltBuffer\r
- //\r
- if (SourceY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (SourceX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- } else {\r
- //\r
- // BltBuffer to Video: Source is BltBuffer, destination is Video\r
- //\r
- if (DestinationY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (DestinationX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
- //\r
- // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
- // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
- // the number of bytes in each row can be computed.\r
- //\r
- if (Delta == 0) {\r
- Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
- }\r
- //\r
- // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
- // We would not want a timer based event (Cursor, ...) to come in while we are\r
- // doing this operation.\r
- //\r
- OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
-\r
- //\r
- // Compute some values we need for VGA\r
- //\r
- switch (BltOperation) {\r
- case EfiBltVideoToBltBuffer:\r
-\r
- SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);\r
- SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;\r
-\r
- //\r
- // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer\r
- //\r
- VgaReadBitPlanes (\r
- PciIo,\r
- MemAddress + SourceOffset,\r
- VgaFrameBuffer + SourceOffset,\r
- SourceWidth,\r
- Height\r
- );\r
-\r
- //\r
- // Convert VGA Bit Planes to a Graphics Output 32-bit color value\r
- //\r
- BltBuffer += (DestinationY * (Delta >> 2) + DestinationX);\r
- for (Rows = 0, CoordinateY = SourceY; Rows < Height; Rows++, CoordinateY++, BltBuffer += (Delta >> 2)) {\r
- for (Columns = 0, CoordinateX = SourceX; Columns < Width; Columns++, CoordinateX++, BltBuffer++) {\r
- VgaConvertToGraphicsOutputColor (VgaFrameBuffer, CoordinateX, CoordinateY, BltBuffer);\r
- }\r
-\r
- BltBuffer -= Width;\r
- }\r
-\r
- break;\r
-\r
- case EfiBltVideoToVideo:\r
- //\r
- // Check for an aligned Video to Video operation\r
- //\r
- if ((SourceX & 0x07) == 0x00 && (DestinationX & 0x07) == 0x00 && (Width & 0x07) == 0x00) {\r
- //\r
- // Program the Mode Register Write mode 1, Read mode 0\r
- //\r
- WriteGraphicsController (\r
- PciIo,\r
- VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
- VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1\r
- );\r
-\r
- SourceAddress = (UINT8 *) (MemAddress + (SourceY << 6) + (SourceY << 4) + (SourceX >> 3));\r
- DestinationAddress = (UINT8 *) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
- Bytes = Width >> 3;\r
- for (Index = 0, Offset = 0; Index < Height; Index++, Offset += BytesPerScanLine) {\r
- PciIo->CopyMem (\r
- PciIo,\r
- EfiPciIoWidthUint8,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- (UINT64) (UINTN) (DestinationAddress + Offset),\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- (UINT64) (UINTN) (SourceAddress + Offset),\r
- Bytes\r
- );\r
- }\r
- } else {\r
- SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);\r
- SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;\r
-\r
- //\r
- // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer\r
- //\r
- VgaReadBitPlanes (\r
- PciIo,\r
- MemAddress + SourceOffset,\r
- VgaFrameBuffer + SourceOffset,\r
- SourceWidth,\r
- Height\r
- );\r
- }\r
-\r
- break;\r
-\r
- case EfiBltVideoFill:\r
- StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
- Bytes = ((DestinationX + Width - 1) >> 3) - (DestinationX >> 3);\r
- LeftMask = mVgaLeftMaskTable[DestinationX & 0x07];\r
- RightMask = mVgaRightMaskTable[(DestinationX + Width - 1) & 0x07];\r
- if (Bytes == 0) {\r
- LeftMask = (UINT8) (LeftMask & RightMask);\r
- RightMask = 0;\r
- }\r
-\r
- if (LeftMask == 0xff) {\r
- StartAddress--;\r
- Bytes++;\r
- LeftMask = 0;\r
- }\r
-\r
- if (RightMask == 0xff) {\r
- Bytes++;\r
- RightMask = 0;\r
- }\r
-\r
- PixelColor = VgaConvertColor (BltBuffer);\r
-\r
- //\r
- // Program the Mode Register Write mode 2, Read mode 0\r
- //\r
- WriteGraphicsController (\r
- PciIo,\r
- VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
- VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2\r
- );\r
-\r
- //\r
- // Program the Data Rotate/Function Select Register to replace\r
- //\r
- WriteGraphicsController (\r
- PciIo,\r
- VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,\r
- VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE\r
- );\r
-\r
- if (LeftMask != 0) {\r
- //\r
- // Program the BitMask register with the Left column mask\r
- //\r
- WriteGraphicsController (\r
- PciIo,\r
- VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
- LeftMask\r
- );\r
-\r
- for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {\r
- //\r
- // Read data from the bit planes into the latches\r
- //\r
- PciIo->Mem.Read (\r
- PciIo,\r
- EfiPciIoWidthUint8,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- (UINT64) (UINTN) Address,\r
- 1,\r
- &Data\r
- );\r
- //\r
- // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask\r
- //\r
- PciIo->Mem.Write (\r
- PciIo,\r
- EfiPciIoWidthUint8,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- (UINT64) (UINTN) Address,\r
- 1,\r
- &PixelColor\r
- );\r
- }\r
- }\r
-\r
- if (Bytes > 1) {\r
- //\r
- // Program the BitMask register with the middle column mask of 0xff\r
- //\r
- WriteGraphicsController (\r
- PciIo,\r
- VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
- 0xff\r
- );\r
-\r
- for (Index = 0, Address = StartAddress + 1; Index < Height; Index++, Address += BytesPerScanLine) {\r
- PciIo->Mem.Write (\r
- PciIo,\r
- EfiPciIoWidthFillUint8,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- (UINT64) (UINTN) Address,\r
- Bytes - 1,\r
- &PixelColor\r
- );\r
- }\r
- }\r
-\r
- if (RightMask != 0) {\r
- //\r
- // Program the BitMask register with the Right column mask\r
- //\r
- WriteGraphicsController (\r
- PciIo,\r
- VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
- RightMask\r
- );\r
-\r
- for (Index = 0, Address = StartAddress + Bytes; Index < Height; Index++, Address += BytesPerScanLine) {\r
- //\r
- // Read data from the bit planes into the latches\r
- //\r
- PciIo->Mem.Read (\r
- PciIo,\r
- EfiPciIoWidthUint8,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- (UINT64) (UINTN) Address,\r
- 1,\r
- &Data\r
- );\r
- //\r
- // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask\r
- //\r
- PciIo->Mem.Write (\r
- PciIo,\r
- EfiPciIoWidthUint8,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- (UINT64) (UINTN) Address,\r
- 1,\r
- &PixelColor\r
- );\r
- }\r
- }\r
- break;\r
-\r
- case EfiBltBufferToVideo:\r
- StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
- LeftMask = mVgaBitMaskTable[DestinationX & 0x07];\r
-\r
- //\r
- // Program the Mode Register Write mode 2, Read mode 0\r
- //\r
- WriteGraphicsController (\r
- PciIo,\r
- VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
- VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2\r
- );\r
-\r
- //\r
- // Program the Data Rotate/Function Select Register to replace\r
- //\r
- WriteGraphicsController (\r
- PciIo,\r
- VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,\r
- VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE\r
- );\r
-\r
- for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {\r
- for (Index1 = 0; Index1 < Width; Index1++) {\r
- BiosVideoPrivate->LineBuffer[Index1] = VgaConvertColor (&BltBuffer[(SourceY + Index) * (Delta >> 2) + SourceX + Index1]);\r
- }\r
- AddressFix = Address;\r
-\r
- for (Bit = 0; Bit < 8; Bit++) {\r
- //\r
- // Program the BitMask register with the Left column mask\r
- //\r
- WriteGraphicsController (\r
- PciIo,\r
- VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
- LeftMask\r
- );\r
-\r
- for (Index1 = Bit, Address1 = (UINT8 *) AddressFix; Index1 < Width; Index1 += 8, Address1++) {\r
- //\r
- // Read data from the bit planes into the latches\r
- //\r
- PciIo->Mem.Read (\r
- PciIo,\r
- EfiPciIoWidthUint8,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- (UINT64) (UINTN) Address1,\r
- 1,\r
- &Data\r
- );\r
-\r
- PciIo->Mem.Write (\r
- PciIo,\r
- EfiPciIoWidthUint8,\r
- EFI_PCI_IO_PASS_THROUGH_BAR,\r
- (UINT64) (UINTN) Address1,\r
- 1,\r
- &BiosVideoPrivate->LineBuffer[Index1]\r
- );\r
- }\r
-\r
- LeftMask = (UINT8) (LeftMask >> 1);\r
- if (LeftMask == 0) {\r
- LeftMask = 0x80;\r
- AddressFix++;\r
- }\r
- }\r
- }\r
-\r
- break;\r
-\r
- default: ;\r
- }\r
-\r
- gBS->RestoreTPL (OriginalTPL);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-//\r
-// VGA Mini Port Protocol Functions\r
-//\r
-\r
-/**\r
- VgaMiniPort protocol interface to set mode.\r
-\r
- @param This Pointer to VgaMiniPort protocol instance\r
- @param ModeNumber The index of the mode\r
-\r
- @retval EFI_UNSUPPORTED The requested mode is not supported\r
- @retval EFI_SUCCESS The requested mode is set successfully\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BiosVideoVgaMiniPortSetMode (\r
- IN EFI_VGA_MINI_PORT_PROTOCOL *This,\r
- IN UINTN ModeNumber\r
- )\r
-{\r
- BIOS_VIDEO_DEV *BiosVideoPrivate;\r
- EFI_IA32_REGISTER_SET Regs;\r
-\r
- if (This == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Make sure the ModeNumber is a valid value\r
- //\r
- if (ModeNumber >= This->MaxMode) {\r
- return EFI_UNSUPPORTED;\r
- }\r
- //\r
- // Get the device structure for this device\r
- //\r
- BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This);\r
-\r
- switch (ModeNumber) {\r
- case 0:\r
- //\r
- // Set the 80x25 Text VGA Mode\r
- //\r
- Regs.H.AH = 0x00;\r
- Regs.H.AL = 0x83;\r
- BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
-\r
- Regs.H.AH = 0x11;\r
- Regs.H.AL = 0x14;\r
- Regs.H.BL = 0;\r
- BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
- break;\r
-\r
- case 1:\r
- //\r
- // Set the 80x50 Text VGA Mode\r
- //\r
- Regs.H.AH = 0x00;\r
- Regs.H.AL = 0x83;\r
- BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
- Regs.H.AH = 0x11;\r
- Regs.H.AL = 0x12;\r
- Regs.H.BL = 0;\r
- BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
- break;\r
-\r
- default:\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Event handler for Exit Boot Service.\r
-\r
- @param Event The event that be siganlled when exiting boot service.\r
- @param Context Pointer to instance of BIOS_VIDEO_DEV.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-BiosVideoNotifyExitBootServices (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- BIOS_VIDEO_DEV *BiosVideoPrivate;\r
- EFI_IA32_REGISTER_SET Regs;\r
-\r
- BiosVideoPrivate = (BIOS_VIDEO_DEV *)Context;\r
-\r
- //\r
- // Set the 80x25 Text VGA Mode\r
- //\r
- Regs.H.AH = 0x00;\r
- Regs.H.AL = 0x03;\r
- BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
-\r
- Regs.H.AH = 0x00;\r
- Regs.H.AL = 0x83;\r
- BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
-\r
- Regs.H.AH = 0x11;\r
- Regs.H.AL = 0x04;\r
- Regs.H.BL = 0;\r
- BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
-}\r
-\r
-/**\r
- The user Entry Point for module UefiBiosVideo. The user code starts with this function.\r
-\r
- @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
- @param[in] SystemTable A pointer to the EFI System Table.\r
-\r
- @retval EFI_SUCCESS The entry point is executed successfully.\r
- @retval other Some error occurs when executing this entry point.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BiosVideoEntryPoint(\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Install driver model protocol(s).\r
- //\r
- Status = EfiLibInstallDriverBindingComponentName2 (\r
- ImageHandle,\r
- SystemTable,\r
- &gBiosVideoDriverBinding,\r
- ImageHandle,\r
- &gBiosVideoComponentName,\r
- &gBiosVideoComponentName2\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver\r
- //\r
- return gBS->InstallMultipleProtocolInterfaces (\r
- &ImageHandle,\r
- &gEfiLegacyBiosGuid,\r
- NULL,\r
- NULL\r
- );\r
-}\r
-\r