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; }