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
QemuVideoCompleteModeInfo(IN QEMU_VIDEO_MODE_DATA * ModeData,OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION * Info)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
QemuVideoCompleteModeData(IN QEMU_VIDEO_PRIVATE_DATA * Private,OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE * Mode)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
QemuVideoGraphicsOutputQueryMode(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN UINT32 ModeNumber,OUT UINTN * SizeOfInfo,OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ** Info)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
QemuVideoGraphicsOutputSetMode(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN UINT32 ModeNumber)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
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)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
QemuVideoGraphicsOutputConstructor(QEMU_VIDEO_PRIVATE_DATA * Private)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
QemuVideoGraphicsOutputDestructor(QEMU_VIDEO_PRIVATE_DATA * Private)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