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