// // Graphics Output Protocol Member Functions // EFI_STATUS EFIAPI QemuVideoGraphicsOutputQueryMode ( IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, IN UINT32 ModeNumber, OUT UINTN *SizeOfInfo, OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info ) /*++ Routine Description: Graphics Output protocol interface to query video mode Arguments: This - Protocol instance pointer. ModeNumber - The mode number to return information on. Info - Caller allocated buffer that returns information about ModeNumber. SizeOfInfo - A pointer to the size, in bytes, of the Info buffer. Returns: EFI_SUCCESS - Mode information returned. EFI_BUFFER_TOO_SMALL - The Info buffer was too small. EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode. EFI_NOT_STARTED - Video display is not initialized. Call SetMode () EFI_INVALID_PARAMETER - One of the input args was NULL. --*/ { QEMU_VIDEO_PRIVATE_DATA *Private; QEMU_VIDEO_MODE_DATA *ModeData; Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This); if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) { return EFI_INVALID_PARAMETER; } *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)); if (*Info == NULL) { return EFI_OUT_OF_RESOURCES; } *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) { CopyMem (*Info, &Private->VmwareSvgaModeInfo[ModeNumber], sizeof (**Info)); } else { ModeData = &Private->ModeData[ModeNumber]; (*Info)->HorizontalResolution = ModeData->HorizontalResolution; (*Info)->VerticalResolution = ModeData->VerticalResolution; QemuVideoCompleteModeInfo (ModeData, *Info); } return EFI_SUCCESS; }
EFI_STATUS EFIAPI QemuVideoGraphicsOutputBlt ( IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, IN UINTN SourceX, IN UINTN SourceY, IN UINTN DestinationX, IN UINTN DestinationY, IN UINTN Width, IN UINTN Height, IN UINTN Delta ) /*++ Routine Description: Graphics Output protocol instance to block transfer for CirrusLogic device Arguments: This - Pointer to Graphics Output protocol instance BltBuffer - The data to transfer to screen BltOperation - The operation to perform SourceX - The X coordinate of the source for BltOperation SourceY - The Y coordinate of the source for BltOperation DestinationX - The X coordinate of the destination for BltOperation DestinationY - The Y coordinate of the destination for BltOperation Width - The width of a rectangle in the blt rectangle in pixels Height - The height of a rectangle in the blt rectangle in pixels Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation. If a Delta of 0 is used, the entire BltBuffer will be operated on. If a subrectangle of the BltBuffer is used, then Delta represents the number of bytes in a row of the BltBuffer. Returns: EFI_INVALID_PARAMETER - Invalid parameter passed in EFI_SUCCESS - Blt operation success --*/ { EFI_STATUS Status; EFI_TPL OriginalTPL; QEMU_VIDEO_PRIVATE_DATA *Private; Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This); // // We have to raise to TPL Notify, so we make an atomic write the frame buffer. // We would not want a timer based event (Cursor, ...) to come in while we are // doing this operation. // OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY); switch (BltOperation) { case EfiBltVideoToBltBuffer: case EfiBltBufferToVideo: case EfiBltVideoFill: case EfiBltVideoToVideo: Status = FrameBufferBlt ( Private->FrameBufferBltConfigure, BltBuffer, BltOperation, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta ); break; default: Status = EFI_INVALID_PARAMETER; ASSERT (FALSE); } gBS->RestoreTPL (OriginalTPL); return Status; }
EFI_STATUS EFIAPI QemuVideoGraphicsOutputSetMode ( IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, IN UINT32 ModeNumber ) /*++ Routine Description: Graphics Output protocol interface to set video mode Arguments: This - Protocol instance pointer. ModeNumber - The mode number to be set. Returns: EFI_SUCCESS - Graphics mode was changed. EFI_DEVICE_ERROR - The device had an error and could not complete the request. EFI_UNSUPPORTED - ModeNumber is not supported by this device. --*/ { QEMU_VIDEO_PRIVATE_DATA *Private; QEMU_VIDEO_MODE_DATA *ModeData; RETURN_STATUS Status; Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This); if (ModeNumber >= This->Mode->MaxMode) { return EFI_UNSUPPORTED; } ModeData = &Private->ModeData[ModeNumber]; switch (Private->Variant) { case QEMU_VIDEO_CIRRUS_5430: case QEMU_VIDEO_CIRRUS_5446: InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]); break; case QEMU_VIDEO_BOCHS_MMIO: case QEMU_VIDEO_BOCHS: InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]); break; default: ASSERT (FALSE); return EFI_DEVICE_ERROR; } This->Mode->Mode = ModeNumber; This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution; This->Mode->Info->VerticalResolution = ModeData->VerticalResolution; This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); QemuVideoCompleteModeData (Private, This->Mode); // // Allocate when using first time. // if (Private->FrameBufferBltConfigure == NULL) { Status = FrameBufferBltConfigure ( (VOID*) (UINTN) This->Mode->FrameBufferBase, This->Mode->Info, Private->FrameBufferBltConfigure, &Private->FrameBufferBltConfigureSize ); ASSERT (Status == RETURN_BUFFER_TOO_SMALL); Private->FrameBufferBltConfigure = AllocatePool (Private->FrameBufferBltConfigureSize); } // // Create the configuration for FrameBufferBltLib // ASSERT (Private->FrameBufferBltConfigure != NULL); Status = FrameBufferBltConfigure ( (VOID*) (UINTN) This->Mode->FrameBufferBase, This->Mode->Info, Private->FrameBufferBltConfigure, &Private->FrameBufferBltConfigureSize ); ASSERT (Status == RETURN_SUCCESS); return EFI_SUCCESS; }
EFI_STATUS EFIAPI QemuVideoGraphicsOutputSetMode ( IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, IN UINT32 ModeNumber ) /*++ Routine Description: Graphics Output protocol interface to set video mode Arguments: This - Protocol instance pointer. ModeNumber - The mode number to be set. Returns: EFI_SUCCESS - Graphics mode was changed. EFI_DEVICE_ERROR - The device had an error and could not complete the request. EFI_UNSUPPORTED - ModeNumber is not supported by this device. --*/ { QEMU_VIDEO_PRIVATE_DATA *Private; QEMU_VIDEO_MODE_DATA *ModeData; // UINTN Count; BOOLEAN VideoModeChanged; Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This); if (ModeNumber >= This->Mode->MaxMode) { return EFI_UNSUPPORTED; } ModeData = &Private->ModeData[ModeNumber]; if (Private->LineBuffer) { gBS->FreePool (Private->LineBuffer); } Private->LineBuffer = AllocatePool (4 * ModeData->HorizontalResolution); if (Private->LineBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } switch (Private->Variant) { case QEMU_VIDEO_CIRRUS_5430: case QEMU_VIDEO_CIRRUS_5446: InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]); break; case QEMU_VIDEO_BOCHS_MMIO: case QEMU_VIDEO_BOCHS: InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]); break; default: ASSERT (FALSE); gBS->FreePool (Private->LineBuffer); Private->LineBuffer = NULL; return EFI_DEVICE_ERROR; } // Check if this is a new mode VideoModeChanged = (This->Mode->Mode != ModeNumber); This->Mode->Mode = ModeNumber; This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution; This->Mode->Info->VerticalResolution = ModeData->VerticalResolution; This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); QemuVideoCompleteModeData (Private, This->Mode); BltLibConfigure ( (VOID*)(UINTN) This->Mode->FrameBufferBase, This->Mode->Info ); if (VideoModeChanged) { UINTN Index; UINTN HandleCount; EFI_HANDLE *HandleBuffer; EFI_STATUS Status; // // Set PCDs to Inform GraphicsConsole of video resolution. // PcdSet32 (PcdVideoHorizontalResolution, This->Mode->Info->HorizontalResolution); PcdSet32 (PcdVideoVerticalResolution, This->Mode->Info->VerticalResolution); // // Video mode is changed, so restart graphics console driver and higher level driver. // Reconnect graphics console driver and higher level driver. // Locate all the handles with GOP protocol and reconnect it. // Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiSimpleTextOutProtocolGuid, NULL, &HandleCount, &HandleBuffer ); if (!EFI_ERROR (Status)) { for (Index = 0; Index < HandleCount; Index++) { gBS->DisconnectController (HandleBuffer[Index], NULL, NULL); } for (Index = 0; Index < HandleCount; Index++) { gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); } if (HandleBuffer != NULL) { FreePool (HandleBuffer); } } } return EFI_SUCCESS; }