+++ /dev/null
-/** @file\r
-\r
- BiosVideo driver produce EFI_GRAPHIC_OUTPUT_PROTOCOL via LegacyBios Video rom.\r
-\r
-Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \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
-EFI_LEGACY_8259_PROTOCOL *mLegacy8259 = NULL;\r
-THUNK_CONTEXT mThunkContext;\r
-\r
-EFI_GRAPHICS_OUTPUT_BLT_PIXEL mVgaColorToGraphicsOutputColor[] = {\r
- //\r
- // {B, G, R, reserved}\r
- // \r
- {0x00, 0x00, 0x00, 0x00}, // BLACK\r
- {0x98, 0x00, 0x00, 0x00}, // LIGHTBLUE\r
- {0x00, 0x98, 0x00, 0x00}, // LIGHGREEN\r
- {0x98, 0x98, 0x00, 0x00}, // LIGHCYAN\r
- {0x00, 0x00, 0x98, 0x00}, // LIGHRED\r
- {0x98, 0x00, 0x98, 0x00}, // MAGENTA\r
- {0x00, 0x98, 0x98, 0x00}, // BROWN\r
- {0x98, 0x98, 0x98, 0x00}, // LIGHTGRAY\r
- {0x10, 0x10, 0x10, 0x00},\r
- {0xff, 0x10, 0x10, 0x00}, // BLUE\r
- {0x10, 0xff, 0x10, 0x00}, // LIME\r
- {0xff, 0xff, 0x10, 0x00}, // CYAN\r
- {0x10, 0x10, 0xff, 0x00}, // RED\r
- {0xf0, 0x10, 0xff, 0x00}, // FUCHSIA\r
- {0x10, 0xff, 0xff, 0x00}, // YELLOW\r
- {0xff, 0xff, 0xff, 0x00} // WHITE \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
- Install child handle for a detect BiosVideo device and install related protocol\r
- into this handle, such as EFI_GRAPHIC_OUTPUT_PROTOCOL.\r
-\r
- @param This Instance pointer of EFI_DRIVER_BINDING_PROTOCOL\r
- @param ParentHandle Parent's controller handle\r
- @param ParentPciIo Parent's EFI_PCI_IO_PROTOCOL instance pointer\r
- @param ParentLegacy8259 Parent's EFI_LEGACY_8259_PROTOCOL instance pointer \r
- @param ParentDevicePath Parent's BIOS Video controller device path\r
- @param RemainingDevicePath Remaining device path node instance for children.\r
-\r
- @return whether success to create children handle for a VGA device and install \r
- related protocol into new children handle.\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_8259_PROTOCOL *ParentLegacy8259,\r
- IN THUNK_CONTEXT *ThunkContext,\r
- IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\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
-\r
-EFI_STATUS\r
-BiosVideoChildHandleUninstall (\r
- EFI_DRIVER_BINDING_PROTOCOL *This,\r
- EFI_HANDLE Controller,\r
- EFI_HANDLE Handle\r
- )\r
-;\r
-\r
-/**\r
- Collect the resource from destroyed bios video device.\r
-\r
- @param BiosVideoPrivate Video child device private data structure\r
-**/\r
-\r
-VOID\r
-BiosVideoDeviceReleaseResource (\r
- BIOS_VIDEO_DEV *BiosVideoPrivate\r
- )\r
-;\r
-\r
-/**\r
- Driver Entry Point.\r
-\r
- @param ImageHandle Handle of driver image.\r
- @param SystemTable Pointer to system table.\r
-\r
- @return EFI_STATUS\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BiosVideoDriverEntryPoint (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = EfiLibInstallDriverBindingComponentName2 (\r
- ImageHandle,\r
- SystemTable,\r
- &gBiosVideoDriverBinding,\r
- ImageHandle,\r
- &gBiosVideoComponentName,\r
- &gBiosVideoComponentName2\r
- );\r
- \r
- return Status;\r
-}\r
-\r
-/**\r
- Test to see if Bios Video could be supported on the Controller.\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 path\r
-\r
- @retval EFI_SUCCESS This driver supports this device.\r
- @retval other This driver does not support this device.\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_8259_PROTOCOL *LegacyBios;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
-\r
- //\r
- // See if the Legacy 8259 Protocol is available\r
- //\r
- Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, 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)) {\r
- return Status;\r
- }\r
-\r
- if (!BiosVideoIsVga (PciIo)) {\r
- Status = EFI_UNSUPPORTED;\r
- }\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- return Status;\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 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
-\r
- PciIo = NULL;\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
- goto Done;\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)) {\r
- goto Done;\r
- }\r
-\r
- //\r
- // Establish legacy environment for thunk call for all children handle.\r
- //\r
- if (mLegacy8259 == NULL) {\r
- Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &mLegacy8259);\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- \r
- InitializeBiosIntCaller(&mThunkContext);\r
- InitializeInterruptRedirection(mLegacy8259);\r
- }\r
-\r
- //\r
- // Create child handle and install GraphicsOutputProtocol on it\r
- //\r
- Status = BiosVideoChildHandleInstall (\r
- This,\r
- Controller,\r
- PciIo,\r
- mLegacy8259,\r
- &mThunkContext,\r
- ParentDevicePath,\r
- RemainingDevicePath\r
- );\r
-\r
-Done:\r
- if (EFI_ERROR (Status)) {\r
- if (PciIo != NULL) {\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
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Stop this driver on Controller \r
-\r
- @param This Protocol instance pointer.\r
- @param Controller Handle of device to stop driver on\r
- @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
- children is zero stop the entire bus driver.\r
- @param ChildHandleBuffer List of Child Handles to Stop.\r
-\r
- @retval EFI_SUCCESS This driver is removed Controller.\r
- @retval other This driver was not removed from this device.\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
-\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
- AllChildrenStopped = TRUE;\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
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Install child handle for a detect BiosVideo device and install related protocol\r
- into this handle, such as EFI_GRAPHIC_OUTPUT_PROTOCOL.\r
-\r
- @param This Instance pointer of EFI_DRIVER_BINDING_PROTOCOL\r
- @param ParentHandle Parent's controller handle\r
- @param ParentPciIo Parent's EFI_PCI_IO_PROTOCOL instance pointer\r
- @param ParentLegacy8259 Parent's EFI_LEGACY_8259_PROTOCOL instance pointer \r
- @param ParentDevicePath Parent's BIOS Video controller device path\r
- @param RemainingDevicePath Remaining device path node instance for children.\r
-\r
- @return whether success to create children handle for a VGA device and install \r
- related protocol into new children handle.\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_8259_PROTOCOL *ParentLegacy8259,\r
- IN THUNK_CONTEXT *ParentThunkContext,\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
- ACPI_ADR_DEVICE_PATH AcpiDeviceNode;\r
-\r
- //\r
- // Allocate the private device structure for video device\r
- //\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- sizeof (BIOS_VIDEO_DEV),\r
- (VOID**) &BiosVideoPrivate\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- ZeroMem (BiosVideoPrivate, sizeof (BIOS_VIDEO_DEV));\r
-\r
- if (!BiosVideoIsVga (ParentPciIo)) {\r
- Status = EFI_UNSUPPORTED;\r
- goto Done;\r
- }\r
- \r
- BiosVideoPrivate->VgaCompatible = TRUE;\r
-\r
- //\r
- // Initialize the child private structure\r
- //\r
- BiosVideoPrivate->Signature = BIOS_VIDEO_DEV_SIGNATURE;\r
- BiosVideoPrivate->Handle = NULL;\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 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
- // Assume that Graphics Output Protocol will be produced until proven otherwise\r
- //\r
- BiosVideoPrivate->ProduceGraphicsOutput = TRUE;\r
-\r
- //\r
- // Child handle need to consume the Legacy Bios protocol\r
- //\r
- BiosVideoPrivate->Legacy8259 = ParentLegacy8259;\r
- BiosVideoPrivate->ThunkContext = ParentThunkContext;\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
- Status = BiosVideoCheckForVbe (BiosVideoPrivate);\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
- if (BiosVideoPrivate->VgaCompatible) {\r
- Status = BiosVideoCheckForVga (BiosVideoPrivate);\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\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
- if (BiosVideoPrivate->ProduceGraphicsOutput) {\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->DevicePath = AppendDevicePathNode (\r
- ParentDevicePath, \r
- (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode\r
- );\r
- } else {\r
- BiosVideoPrivate->DevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);\r
- }\r
-\r
- //\r
- // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol\r
- //\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &BiosVideoPrivate->Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- BiosVideoPrivate->DevicePath,\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
- }\r
- } else {\r
- //\r
- // Install VGA Mini Port Protocol\r
- //\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &BiosVideoPrivate->Handle,\r
- &gEfiVgaMiniPortProtocolGuid,\r
- &BiosVideoPrivate->VgaMiniPort,\r
- NULL\r
- );\r
- }\r
-\r
-Done:\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Free private data structure\r
- //\r
- BiosVideoDeviceReleaseResource (BiosVideoPrivate);\r
- }\r
-\r
- return Status;\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
- 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
-\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
- 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
- if (BiosVideoPrivate == NULL) {\r
- return EFI_UNSUPPORTED;\r
- }\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->DevicePath,\r
- &gEfiGraphicsOutputProtocolGuid,\r
- &BiosVideoPrivate->GraphicsOutput,\r
- &gEfiEdidDiscoveredProtocolGuid,\r
- &BiosVideoPrivate->EdidDiscovered,\r
- &gEfiEdidActiveProtocolGuid,\r
- &BiosVideoPrivate->EdidActive,\r
- NULL\r
- );\r
- } else {\r
- Status = gBS->UninstallMultipleProtocolInterfaces (\r
- BiosVideoPrivate->Handle,\r
- &gEfiVgaMiniPortProtocolGuid,\r
- &BiosVideoPrivate->VgaMiniPort,\r
- NULL\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
- gBS->SetMem (&Regs, sizeof (Regs), 0);\r
-\r
- //\r
- // Set the 80x25 Text VGA Mode\r
- //\r
- Regs.H.AH = 0x00;\r
- Regs.H.AL = 0x03;\r
- LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
- \r
- Regs.H.AH = 0x11;\r
- Regs.H.AL = 0x14;\r
- Regs.H.BL = 0;\r
- LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
- \r
- //\r
- // Do not disable IO/memory decode since that would prevent legacy ROM from working\r
- //\r
-\r
- //\r
- // Release all allocated resources\r
- //\r
- BiosVideoDeviceReleaseResource (BiosVideoPrivate);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Collect the resource from destroyed bios video device.\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
- gBS->FreePool (BiosVideoPrivate->VgaFrameBuffer);\r
- }\r
- //\r
- // Free VBE Frame Buffer\r
- //\r
- if (BiosVideoPrivate->VbeFrameBuffer != NULL) {\r
- gBS->FreePool (BiosVideoPrivate->VbeFrameBuffer);\r
- }\r
- //\r
- // Free line buffer\r
- //\r
- if (BiosVideoPrivate->LineBuffer != NULL) {\r
- gBS->FreePool (BiosVideoPrivate->LineBuffer);\r
- }\r
- //\r
- // Free mode data\r
- //\r
- if (BiosVideoPrivate->ModeData != NULL) {\r
- gBS->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
- // Free graphics output protocol occupied resource\r
- //\r
- if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
- if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
- gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
- }\r
- gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
- }\r
- //\r
- // Free EDID discovered protocol occupied resource\r
- //\r
- if (BiosVideoPrivate->EdidDiscovered.Edid != NULL) {\r
- gBS->FreePool (BiosVideoPrivate->EdidDiscovered.Edid);\r
- }\r
- //\r
- // Free EDID active protocol occupied resource\r
- //\r
- if (BiosVideoPrivate->EdidActive.Edid != NULL) {\r
- gBS->FreePool (BiosVideoPrivate->EdidActive.Edid);\r
- }\r
-\r
- if (BiosVideoPrivate->DevicePath!= NULL) {\r
- gBS->FreePool (BiosVideoPrivate->DevicePath);\r
- }\r
-\r
- gBS->FreePool (BiosVideoPrivate);\r
-\r
- return ;\r
-}\r
-\r
-/**\r
-\r
- Generate a search key for a specified timing data.\r
-\r
-\r
- @param EdidTiming - Pointer to EDID timing\r
-\r
- @return The 32 bit unique key for search.\r
-\r
-**/\r
-STATIC\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
-\r
- @param EdidBuffer - Pointer to EDID data block\r
- @param ValidEdidTiming - Valid EDID timing information\r
-\r
- @return TRUE - The EDID data is valid.\r
- FALSE - The EDID data is invalid.\r
-\r
-**/\r
-STATIC\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) {\r
- ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&mEstablishedEdidTiming[Index]);\r
- ValidNumber ++;\r
- }\r
- TimingBits = TimingBits >> 1;\r
- }\r
- } else {\r
- //\r
- // If no Established timing data, read the standard timing data\r
- //\r
- BufferIndex = &EdidDataBlock->StandardTimingIdentification[0];\r
- for (Index = 0; Index < 8; Index ++) {\r
- if ((BufferIndex[0] != 0x1) && (BufferIndex[1] != 0x1)){\r
- //\r
- // A valid Standard Timing\r
- //\r
- HorizontalResolution = (UINT8) (BufferIndex[0] * 8 + 248);\r
- AspectRatio = (UINT8) (BufferIndex[1] >> 6);\r
- switch (AspectRatio) {\r
- case 0:\r
- VerticalResolution = (UINT8) (HorizontalResolution / 16 * 10);\r
- break;\r
- case 1:\r
- VerticalResolution = (UINT8) (HorizontalResolution / 4 * 3);\r
- break;\r
- case 2:\r
- VerticalResolution = (UINT8) (HorizontalResolution / 5 * 4);\r
- break;\r
- case 3:\r
- VerticalResolution = (UINT8) (HorizontalResolution / 16 * 9);\r
- break;\r
- default:\r
- VerticalResolution = (UINT8) (HorizontalResolution / 4 * 3);\r
- break;\r
- }\r
- RefreshRate = (UINT8) ((BufferIndex[1] & 0x1f) + 60);\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
- ValidEdidTiming->ValidNumber = ValidNumber;\r
- return TRUE;\r
-}\r
-\r
-/**\r
-\r
- Search a specified Timing in all the valid EDID timings.\r
-\r
-\r
- @param ValidEdidTiming - All valid EDID timing information.\r
- @param EdidTiming - The Timing to search for.\r
-\r
- @return TRUE - Found.\r
- FALSE - Not found.\r
-\r
-**/\r
-STATIC\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
-#define PCI_DEVICE_ENABLED (EFI_PCI_COMMAND_IO_SPACE | EFI_PCI_COMMAND_MEMORY_SPACE)\r
-\r
-\r
-/**\r
- Judge whether this device is VGA device.\r
-\r
- @param PciIo Parent PciIo protocol instance pointer\r
-\r
- @retval TRUE Is vga device\r
- @retval FALSE Is no vga device\r
-**/\r
-BOOLEAN\r
-BiosVideoIsVga (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BOOLEAN VgaCompatible;\r
- PCI_TYPE00 Pci;\r
-\r
- VgaCompatible = FALSE;\r
-\r
- //\r
- // Read the PCI Configuration Header\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
- return VgaCompatible;\r
- }\r
-\r
- //\r
- // See if this is a VGA compatible controller or not\r
- //\r
- if ((Pci.Hdr.Command & PCI_DEVICE_ENABLED) == PCI_DEVICE_ENABLED) {\r
- if (Pci.Hdr.ClassCode[2] == PCI_CLASS_OLD && Pci.Hdr.ClassCode[1] == PCI_CLASS_OLD_VGA) {\r
- //\r
- // Base Class 0x00 Sub-Class 0x01 - Backward compatible VGA device\r
- //\r
- VgaCompatible = TRUE;\r
- }\r
-\r
- if (Pci.Hdr.ClassCode[2] == PCI_CLASS_DISPLAY && Pci.Hdr.ClassCode[1] == PCI_CLASS_DISPLAY_VGA && Pci.Hdr.ClassCode[0] == 0x00) {\r
- //\r
- // Base Class 3 Sub-Class 0 Programming interface 0 - VGA compatible Display controller\r
- //\r
- VgaCompatible = TRUE;\r
- }\r
- }\r
-\r
- return VgaCompatible;\r
-}\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
-EFIAPI\r
-BiosVideoCheckForVbe (\r
- IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate\r
- )\r
-{\r
- EFI_STATUS Status;\r
- IA32_REGISTER_SET Regs;\r
- UINT16 *ModeNumberPtr;\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_GRAPHICS_OUTPUT_PROTOCOL_MODE *GraphicsOutputMode;\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 Graphics Output Protocol\r
- //\r
- BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode;\r
- BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode;\r
- BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVbeBlt;\r
- BiosVideoPrivate->GraphicsOutput.Mode = NULL;\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
- // INT 10 - VESA SuperVGA BIOS (VBE) - GET SuperVGA INFORMATION\r
- //\r
- // AX = 4F00h\r
- // ES:DI -> buffer for SuperVGA information (see #00077)\r
- // Return: AL = 4Fh if function supported\r
- // AH = status\r
- // 00h successful\r
- // ES:DI buffer filled\r
- // 01h failed\r
- // ---VBE v2.0---\r
- // 02h function not supported by current hardware configuration\r
- // 03h function invalid in current video mode\r
- // Desc: determine whether VESA BIOS extensions are present and the capabilities\r
- // supported by the display adapter\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.E.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeInformationBlock);\r
- Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeInformationBlock);\r
-\r
- LegacyBiosInt86 (BiosVideoPrivate, 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
- //\r
- // Read EDID information\r
- //\r
- // INT 10 - VESA VBE/DC (Display Data Channel) - READ EDID\r
- //\r
- // AX = 4F15h\r
- // BL = 01h\r
- // CX = 0000h\r
- // DX = 0000h\r
- // ES:DI -> 128-byte buffer for EDID record (see #00127)\r
- // Return: AL = 4Fh if function supported\r
- // AH = status\r
- // 00h successful\r
- // ES:DI buffer filled\r
- // 01h failed (e.g. non-DDC monitor)\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.E.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);\r
- Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);\r
-\r
- LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
- \r
- //\r
- // See if the VESA call succeeded\r
- //\r
- EdidFound = FALSE;\r
- if (Regs.X.AX == VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
- //\r
- // Parse EDID data structure to retrieve modes supported by monitor\r
- //\r
- if (ParseEdidData ((UINT8 *) BiosVideoPrivate->VbeEdidDataBlock, &ValidEdidTiming) == TRUE) {\r
- EdidFound = TRUE;\r
-\r
- BiosVideoPrivate->EdidDiscovered.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,\r
- (VOID**) &BiosVideoPrivate->EdidDiscovered.Edid\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- gBS->CopyMem (\r
- BiosVideoPrivate->EdidDiscovered.Edid,\r
- BiosVideoPrivate->VbeEdidDataBlock,\r
- VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE\r
- );\r
-\r
- BiosVideoPrivate->EdidActive.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,\r
- (VOID**)&BiosVideoPrivate->EdidActive.Edid\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- gBS->CopyMem (\r
- BiosVideoPrivate->EdidActive.Edid,\r
- BiosVideoPrivate->VbeEdidDataBlock,\r
- VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE\r
- );\r
- } else {\r
- BiosVideoPrivate->EdidDiscovered.SizeOfEdid = 0;\r
- BiosVideoPrivate->EdidDiscovered.Edid = NULL;\r
-\r
- BiosVideoPrivate->EdidActive.SizeOfEdid = 0;\r
- BiosVideoPrivate->EdidActive.Edid = NULL;\r
- }\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
- for (; *ModeNumberPtr != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; 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 ((*ModeNumberPtr & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) {\r
- continue;\r
- }\r
- //\r
- // Get the information about the mode\r
- //\r
- // INT 10 - VESA SuperVGA BIOS - GET SuperVGA MODE INFORMATION\r
- //\r
- // AX = 4F01h\r
- // CX = SuperVGA video mode (see #04082 for bitfields)\r
- // ES:DI -> 256-byte buffer for mode information (see #00079)\r
- // Return: AL = 4Fh if function supported\r
- // AH = status\r
- // 00h successful\r
- // ES:DI buffer filled\r
- // 01h failed\r
- // Desc: determine the attributes of the specified video mode\r
- //\r
- gBS->SetMem (&Regs, sizeof (Regs), 0);\r
- Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION;\r
- Regs.X.CX = *ModeNumberPtr;\r
- gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0);\r
- Regs.E.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
- Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
-\r
- LegacyBiosInt86 (BiosVideoPrivate, 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
- 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) == FALSE) {\r
- continue;\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
- 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
- // Add mode to the list of available modes\r
- //\r
- ModeNumber ++;\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- ModeNumber * sizeof (BIOS_VIDEO_MODE_DATA),\r
- (VOID **) &ModeBuffer\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- if (ModeNumber > 1) {\r
- gBS->CopyMem (\r
- ModeBuffer,\r
- BiosVideoPrivate->ModeData,\r
- (ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA)\r
- );\r
- }\r
-\r
- if (BiosVideoPrivate->ModeData != NULL) {\r
- gBS->FreePool (BiosVideoPrivate->ModeData);\r
- }\r
-\r
- CurrentModeData = &ModeBuffer[ModeNumber - 1];\r
- CurrentModeData->VbeModeNumber = *ModeNumberPtr;\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
- 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
- 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->FrameBufferSize = BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024;\r
- CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
- CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
-\r
- CurrentModeData->BitsPerPixel = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel;\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
- // Allocate buffer for Graphics Output Protocol mode information\r
- //\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),\r
- (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- GraphicsOutputMode = BiosVideoPrivate->GraphicsOutput.Mode;\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
- (VOID **) &GraphicsOutputMode->Info\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- GraphicsOutputMode->MaxMode = (UINT32) ModeNumber;\r
- //\r
- // Current mode is unknow till now, set it to an invalid mode.\r
- //\r
- GraphicsOutputMode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
-\r
- //\r
- // Find the best mode to initialize\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
- gBS->FreePool (BiosVideoPrivate->ModeData);\r
- }\r
- if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
- if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
- gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
- }\r
- gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
- }\r
- }\r
-\r
- return Status;\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
-EFI_STATUS\r
-EFIAPI\r
-BiosVideoCheckForVga (\r
- IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BIOS_VIDEO_MODE_DATA *ModeBuffer;\r
- \r
- //\r
- // Fill in the Graphics Output Protocol\r
- //\r
- BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode;\r
- BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode;\r
- BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVgaBlt;\r
-\r
- //\r
- // Allocate buffer for Graphics Output Protocol mode information\r
- //\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),\r
- (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
- (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode->Info\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- //\r
- // Add mode to the list of available modes\r
- //\r
- BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = 1;\r
-\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- sizeof (BIOS_VIDEO_MODE_DATA),\r
- (VOID **) &ModeBuffer\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- ModeBuffer->VbeModeNumber = 0x0012;\r
- ModeBuffer->BytesPerScanLine = 640;\r
- ModeBuffer->LinearFrameBuffer = (VOID *) (UINTN) (0xa0000);\r
- ModeBuffer->FrameBufferSize = 0;\r
- ModeBuffer->HorizontalResolution = 640;\r
- ModeBuffer->VerticalResolution = 480;\r
- ModeBuffer->BitsPerPixel = 8; \r
- ModeBuffer->PixelFormat = PixelBltOnly;\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
- gBS->FreePool (BiosVideoPrivate->ModeData);\r
- }\r
- if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
- if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
- gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
- }\r
- gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
- }\r
- }\r
- return Status;\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
-\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 buffer.\r
- @param Info - Caller allocated buffer that returns information about ModeNumber.\r
-\r
- @return EFI_SUCCESS - Mode information returned.\r
- EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.\r
- EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()\r
- 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
- EFI_STATUS Status;\r
- BIOS_VIDEO_MODE_DATA *ModeData;\r
-\r
- BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
-\r
- if (BiosVideoPrivate->HardwareNeedsStarting) {\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
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
- (VOID**) Info\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\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
- (*Info)->PixelInformation = ModeData->PixelBitMask;\r
-\r
- (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-\r
- Graphics Output protocol interface to set video mode\r
-\r
-\r
- @param This - Protocol instance pointer.\r
- @param ModeNumber - The mode number to be set.\r
-\r
- @return EFI_SUCCESS - Graphics mode was changed.\r
- EFI_DEVICE_ERROR - The device had an error and could not complete the request.\r
- 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
- IA32_REGISTER_SET Regs;\r
- BIOS_VIDEO_MODE_DATA *ModeData;\r
-\r
- BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
-\r
- if (This == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (ModeNumber >= This->Mode->MaxMode) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- ModeData = &BiosVideoPrivate->ModeData[ModeNumber];\r
-\r
- if (BiosVideoPrivate->LineBuffer) {\r
- gBS->FreePool (BiosVideoPrivate->LineBuffer);\r
- }\r
-\r
- if (BiosVideoPrivate->VgaFrameBuffer) {\r
- gBS->FreePool (BiosVideoPrivate->VgaFrameBuffer);\r
- }\r
-\r
- if (BiosVideoPrivate->VbeFrameBuffer) {\r
- gBS->FreePool (BiosVideoPrivate->VbeFrameBuffer);\r
- }\r
-\r
- BiosVideoPrivate->LineBuffer = NULL;\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- ModeData->BytesPerScanLine,\r
- (VOID**) &BiosVideoPrivate->LineBuffer\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- //\r
- // Clear all registers\r
- //\r
- gBS->SetMem (&Regs, sizeof (Regs), 0);\r
-\r
- if (ModeData->VbeModeNumber < 0x100) {\r
- //\r
- // Allocate a working buffer for BLT operations to the VGA frame buffer\r
- //\r
- BiosVideoPrivate->VgaFrameBuffer = NULL;\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- 4 * 480 * 80,\r
- (VOID**) &BiosVideoPrivate->VgaFrameBuffer\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- //\r
- // Set VGA Mode\r
- //\r
- Regs.X.AX = ModeData->VbeModeNumber;\r
- LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
-\r
- } else {\r
- //\r
- // Allocate a working buffer for BLT operations to the VBE frame buffer\r
- //\r
- BiosVideoPrivate->VbeFrameBuffer = NULL;\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- ModeData->BytesPerScanLine * ModeData->VerticalResolution,\r
- (VOID**) &BiosVideoPrivate->VbeFrameBuffer\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\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
- gBS->SetMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK), 0);\r
- Regs.E.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);\r
- Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);\r
- \r
- LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
- \r
- //\r
- // Check to see if the call succeeded\r
- //\r
- if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\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
- 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
- This->Mode->Info->PixelInformation = ModeData->PixelBitMask;\r
- This->Mode->Info->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
- This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
-\r
- //\r
- // Frame BufferSize remain unchanged\r
- //\r
- This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS)(UINTN)ModeData->LinearFrameBuffer;\r
- This->Mode->FrameBufferSize = ModeData->FrameBufferSize;\r
-\r
- BiosVideoPrivate->HardwareNeedsStarting = FALSE;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-\r
- Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.\r
-\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
- @return None.\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
-// BUGBUG : Add Blt for 16 bit color, 15 bit color, and 8 bit color modes\r
-//\r
-/**\r
-\r
- Graphics Output protocol instance to block transfer for VBE device\r
-\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 BltOperation\r
- @param DestinationY - The Y coordinate of the destination for BltOperation\r
- @param Width - The width of a rectangle in the blt rectangle in pixels\r
- @param Height - The height of a rectangle in the blt rectangle in pixels\r
- @param Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.\r
- If a Delta of 0 is used, the entire BltBuffer will be operated on.\r
- If a subrectangle of the BltBuffer is used, then Delta represents\r
- the number of bytes in a row of the BltBuffer.\r
-\r
- @return EFI_INVALID_PARAMETER - Invalid parameter passed in\r
- 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
- 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
- BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
- Mode = &BiosVideoPrivate->ModeData[This->Mode->Mode];\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 (This == NULL || ((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 = *(UINT32 *) (VbeBuffer);\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
- 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
- default:\r
- break;\r
- }\r
-\r
- gBS->RestoreTPL (OriginalTPL);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-\r
- Write graphics controller registers\r
-\r
-\r
- @param PciIo - Pointer to PciIo protocol instance of the controller\r
- @param Address - Register address\r
- @param Data - Data to be written to register\r
-\r
- @return None\r
-\r
-**/\r
-STATIC\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
-\r
- @param PciIo - Pointer to PciIo protocol instance of the 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
- (UINT8) 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
-\r
- @param MemoryBuffer - Buffer containing VGA color\r
- @param X - The X coordinate of pixel on screen\r
- @param Y - 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 X,\r
- UINTN Y,\r
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer\r
- )\r
-{\r
- UINTN Mask;\r
- UINTN Bit;\r
- UINTN Color;\r
-\r
- MemoryBuffer += ((Y << 6) + (Y << 4) + (X >> 3));\r
- Mask = mVgaBitMaskTable[X & 0x07];\r
- for (Bit = 0x01, Color = 0; Bit < 0x10; Bit <<= 1, MemoryBuffer += VGA_BYTES_PER_BIT_PLANE) {\r
- if (*MemoryBuffer & Mask) {\r
- Color |= Bit;\r
- }\r
- }\r
-\r
- *BltBuffer = mVgaColorToGraphicsOutputColor[Color];\r
-}\r
-\r
-/**\r
-\r
- Internal routine to convert Grahpics Output color to VGA color\r
-\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
- 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 BltOperation\r
- @param DestinationY The Y coordinate of the destination for BltOperation\r
- @param Width The width of a rectangle in the blt rectangle in pixels\r
- @param Height The height of a rectangle in the blt rectangle in pixels\r
- @param Delta Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.\r
- If a Delta of 0 is used, the entire BltBuffer will be operated on.\r
- If a subrectangle of the BltBuffer is used, then Delta represents\r
- the number of bytes in a row of 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 BytesPerBitPlane;\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 X;\r
- UINTN Y;\r
- UINTN CurrentMode;\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
- //BytesPerBitPlane = BytesPerScanLine * BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution;\r
- VgaFrameBuffer = BiosVideoPrivate->VgaFrameBuffer;\r
-\r
- if (This == NULL || ((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 > 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, Y = SourceY; Rows < Height; Rows++, Y++, BltBuffer += (Delta >> 2)) {\r
- for (Columns = 0, X = SourceX; Columns < Width; Columns++, X++, BltBuffer++) {\r
- VgaConvertToGraphicsOutputColor (VgaFrameBuffer, X, Y, 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) 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) 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) 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) 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) 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
- default:\r
- break;\r
- }\r
-\r
- gBS->RestoreTPL (OriginalTPL);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-//\r
-// VGA Mini Port Protocol Functions\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
- 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
- gBS->SetMem (&Regs, sizeof (Regs), 0);\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
- LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
- \r
- Regs.H.AH = 0x11;\r
- Regs.H.AL = 0x14;\r
- Regs.H.BL = 0;\r
- LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
- \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
- LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
- \r
- Regs.H.AH = 0x11;\r
- Regs.H.AL = 0x12;\r
- Regs.H.BL = 0;\r
- LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
- break;\r
-\r
- default:\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r