1 /** @file 2 Graphics Output Protocol functions for the QEMU video controller. 3 4 Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR> 5 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 #include "Qemu.h" 17 18 STATIC 19 VOID 20 QemuVideoCompleteModeInfo ( 21 IN QEMU_VIDEO_MODE_DATA *ModeData, 22 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info 23 ) 24 { 25 Info->Version = 0; 26 if (ModeData->ColorDepth == 8) { 27 Info->PixelFormat = PixelBitMask; 28 Info->PixelInformation.RedMask = PIXEL_RED_MASK; 29 Info->PixelInformation.GreenMask = PIXEL_GREEN_MASK; 30 Info->PixelInformation.BlueMask = PIXEL_BLUE_MASK; 31 Info->PixelInformation.ReservedMask = 0; 32 } else if (ModeData->ColorDepth == 24) { 33 Info->PixelFormat = PixelBitMask; 34 Info->PixelInformation.RedMask = PIXEL24_RED_MASK; 35 Info->PixelInformation.GreenMask = PIXEL24_GREEN_MASK; 36 Info->PixelInformation.BlueMask = PIXEL24_BLUE_MASK; 37 Info->PixelInformation.ReservedMask = 0; 38 } else if (ModeData->ColorDepth == 32) { 39 DEBUG ((EFI_D_INFO, "PixelBlueGreenRedReserved8BitPerColor\n")); 40 Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor; 41 } 42 Info->PixelsPerScanLine = Info->HorizontalResolution; 43 } 44 45 46 STATIC 47 EFI_STATUS 48 QemuVideoCompleteModeData ( 49 IN QEMU_VIDEO_PRIVATE_DATA *Private, 50 OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode 51 ) 52 { 53 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; 54 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *FrameBufDesc; 55 QEMU_VIDEO_MODE_DATA *ModeData; 56 57 ModeData = &Private->ModeData[Mode->Mode]; 58 Info = Mode->Info; 59 QemuVideoCompleteModeInfo (ModeData, Info); 60 61 Private->PciIo->GetBarAttributes ( 62 Private->PciIo, 63 0, 64 NULL, 65 (VOID**) &FrameBufDesc 66 ); 67 68 Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin; 69 Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution; 70 Mode->FrameBufferSize = Mode->FrameBufferSize * ((ModeData->ColorDepth + 7) / 8); 71 DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n", 72 Mode->FrameBufferBase, (UINT64)Mode->FrameBufferSize)); 73 74 FreePool (FrameBufDesc); 75 return EFI_SUCCESS; 76 } 77 78 79 // 80 // Graphics Output Protocol Member Functions 81 // 82 EFI_STATUS 83 EFIAPI 84 QemuVideoGraphicsOutputQueryMode ( 85 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, 86 IN UINT32 ModeNumber, 87 OUT UINTN *SizeOfInfo, 88 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info 89 ) 90 /*++ 91 92 Routine Description: 93 94 Graphics Output protocol interface to query video mode 95 96 Arguments: 97 This - Protocol instance pointer. 98 ModeNumber - The mode number to return information on. 99 Info - Caller allocated buffer that returns information about ModeNumber. 100 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer. 101 102 Returns: 103 EFI_SUCCESS - Mode information returned. 104 EFI_BUFFER_TOO_SMALL - The Info buffer was too small. 105 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode. 106 EFI_NOT_STARTED - Video display is not initialized. Call SetMode () 107 EFI_INVALID_PARAMETER - One of the input args was NULL. 108 109 --*/ 110 { 111 QEMU_VIDEO_PRIVATE_DATA *Private; 112 QEMU_VIDEO_MODE_DATA *ModeData; 113 114 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This); 115 116 if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) { 117 return EFI_INVALID_PARAMETER; 118 } 119 120 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)); 121 if (*Info == NULL) { 122 return EFI_OUT_OF_RESOURCES; 123 } 124 125 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); 126 127 ModeData = &Private->ModeData[ModeNumber]; 128 (*Info)->HorizontalResolution = ModeData->HorizontalResolution; 129 (*Info)->VerticalResolution = ModeData->VerticalResolution; 130 QemuVideoCompleteModeInfo (ModeData, *Info); 131 132 return EFI_SUCCESS; 133 } 134 135 EFI_STATUS 136 EFIAPI 137 QemuVideoGraphicsOutputSetMode ( 138 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, 139 IN UINT32 ModeNumber 140 ) 141 /*++ 142 143 Routine Description: 144 145 Graphics Output protocol interface to set video mode 146 147 Arguments: 148 This - Protocol instance pointer. 149 ModeNumber - The mode number to be set. 150 151 Returns: 152 EFI_SUCCESS - Graphics mode was changed. 153 EFI_DEVICE_ERROR - The device had an error and could not complete the request. 154 EFI_UNSUPPORTED - ModeNumber is not supported by this device. 155 156 --*/ 157 { 158 QEMU_VIDEO_PRIVATE_DATA *Private; 159 QEMU_VIDEO_MODE_DATA *ModeData; 160 RETURN_STATUS Status; 161 162 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This); 163 164 if (ModeNumber >= This->Mode->MaxMode) { 165 return EFI_UNSUPPORTED; 166 } 167 168 ModeData = &Private->ModeData[ModeNumber]; 169 170 switch (Private->Variant) { 171 case QEMU_VIDEO_CIRRUS_5430: 172 case QEMU_VIDEO_CIRRUS_5446: 173 InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]); 174 break; 175 case QEMU_VIDEO_BOCHS_MMIO: 176 case QEMU_VIDEO_BOCHS: 177 InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]); 178 break; 179 default: 180 ASSERT (FALSE); 181 return EFI_DEVICE_ERROR; 182 } 183 184 This->Mode->Mode = ModeNumber; 185 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution; 186 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution; 187 This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); 188 189 QemuVideoCompleteModeData (Private, This->Mode); 190 191 // 192 // Allocate when using first time. 193 // 194 if (Private->FrameBufferBltConfigure == NULL) { 195 Status = FrameBufferBltConfigure ( 196 (VOID*) (UINTN) This->Mode->FrameBufferBase, 197 This->Mode->Info, 198 Private->FrameBufferBltConfigure, 199 &Private->FrameBufferBltConfigureSize 200 ); 201 ASSERT (Status == RETURN_BUFFER_TOO_SMALL); 202 Private->FrameBufferBltConfigure = 203 AllocatePool (Private->FrameBufferBltConfigureSize); 204 } 205 206 // 207 // Create the configuration for FrameBufferBltLib 208 // 209 ASSERT (Private->FrameBufferBltConfigure != NULL); 210 Status = FrameBufferBltConfigure ( 211 (VOID*) (UINTN) This->Mode->FrameBufferBase, 212 This->Mode->Info, 213 Private->FrameBufferBltConfigure, 214 &Private->FrameBufferBltConfigureSize 215 ); 216 ASSERT (Status == RETURN_SUCCESS); 217 218 return EFI_SUCCESS; 219 } 220 221 EFI_STATUS 222 EFIAPI 223 QemuVideoGraphicsOutputBlt ( 224 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, 225 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL 226 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, 227 IN UINTN SourceX, 228 IN UINTN SourceY, 229 IN UINTN DestinationX, 230 IN UINTN DestinationY, 231 IN UINTN Width, 232 IN UINTN Height, 233 IN UINTN Delta 234 ) 235 /*++ 236 237 Routine Description: 238 239 Graphics Output protocol instance to block transfer for CirrusLogic device 240 241 Arguments: 242 243 This - Pointer to Graphics Output protocol instance 244 BltBuffer - The data to transfer to screen 245 BltOperation - The operation to perform 246 SourceX - The X coordinate of the source for BltOperation 247 SourceY - The Y coordinate of the source for BltOperation 248 DestinationX - The X coordinate of the destination for BltOperation 249 DestinationY - The Y coordinate of the destination for BltOperation 250 Width - The width of a rectangle in the blt rectangle in pixels 251 Height - The height of a rectangle in the blt rectangle in pixels 252 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation. 253 If a Delta of 0 is used, the entire BltBuffer will be operated on. 254 If a subrectangle of the BltBuffer is used, then Delta represents 255 the number of bytes in a row of the BltBuffer. 256 257 Returns: 258 259 EFI_INVALID_PARAMETER - Invalid parameter passed in 260 EFI_SUCCESS - Blt operation success 261 262 --*/ 263 { 264 EFI_STATUS Status; 265 EFI_TPL OriginalTPL; 266 QEMU_VIDEO_PRIVATE_DATA *Private; 267 268 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This); 269 // 270 // We have to raise to TPL Notify, so we make an atomic write the frame buffer. 271 // We would not want a timer based event (Cursor, ...) to come in while we are 272 // doing this operation. 273 // 274 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY); 275 276 switch (BltOperation) { 277 case EfiBltVideoToBltBuffer: 278 case EfiBltBufferToVideo: 279 case EfiBltVideoFill: 280 case EfiBltVideoToVideo: 281 Status = FrameBufferBlt ( 282 Private->FrameBufferBltConfigure, 283 BltBuffer, 284 BltOperation, 285 SourceX, 286 SourceY, 287 DestinationX, 288 DestinationY, 289 Width, 290 Height, 291 Delta 292 ); 293 break; 294 295 default: 296 Status = EFI_INVALID_PARAMETER; 297 ASSERT (FALSE); 298 } 299 300 gBS->RestoreTPL (OriginalTPL); 301 302 return Status; 303 } 304 305 EFI_STATUS 306 QemuVideoGraphicsOutputConstructor ( 307 QEMU_VIDEO_PRIVATE_DATA *Private 308 ) 309 { 310 EFI_STATUS Status; 311 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; 312 313 314 GraphicsOutput = &Private->GraphicsOutput; 315 GraphicsOutput->QueryMode = QemuVideoGraphicsOutputQueryMode; 316 GraphicsOutput->SetMode = QemuVideoGraphicsOutputSetMode; 317 GraphicsOutput->Blt = QemuVideoGraphicsOutputBlt; 318 319 // 320 // Initialize the private data 321 // 322 Status = gBS->AllocatePool ( 323 EfiBootServicesData, 324 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE), 325 (VOID **) &Private->GraphicsOutput.Mode 326 ); 327 if (EFI_ERROR (Status)) { 328 return Status; 329 } 330 331 Status = gBS->AllocatePool ( 332 EfiBootServicesData, 333 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), 334 (VOID **) &Private->GraphicsOutput.Mode->Info 335 ); 336 if (EFI_ERROR (Status)) { 337 goto FreeMode; 338 } 339 Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode; 340 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER; 341 Private->FrameBufferBltConfigure = NULL; 342 Private->FrameBufferBltConfigureSize = 0; 343 344 // 345 // Initialize the hardware 346 // 347 Status = GraphicsOutput->SetMode (GraphicsOutput, 0); 348 if (EFI_ERROR (Status)) { 349 goto FreeInfo; 350 } 351 352 DrawLogo ( 353 Private, 354 Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution, 355 Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution 356 ); 357 358 return EFI_SUCCESS; 359 360 FreeInfo: 361 FreePool (Private->GraphicsOutput.Mode->Info); 362 363 FreeMode: 364 FreePool (Private->GraphicsOutput.Mode); 365 Private->GraphicsOutput.Mode = NULL; 366 367 return Status; 368 } 369 370 EFI_STATUS 371 QemuVideoGraphicsOutputDestructor ( 372 QEMU_VIDEO_PRIVATE_DATA *Private 373 ) 374 /*++ 375 376 Routine Description: 377 378 Arguments: 379 380 Returns: 381 382 None 383 384 --*/ 385 { 386 if (Private->FrameBufferBltConfigure != NULL) { 387 FreePool (Private->FrameBufferBltConfigure); 388 } 389 390 if (Private->GraphicsOutput.Mode != NULL) { 391 if (Private->GraphicsOutput.Mode->Info != NULL) { 392 gBS->FreePool (Private->GraphicsOutput.Mode->Info); 393 } 394 gBS->FreePool (Private->GraphicsOutput.Mode); 395 } 396 397 return EFI_SUCCESS; 398 } 399 400 401