]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/QemuVideoDxe/Gop.c
QemuVideo: stdvga mmio bar support
[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 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 (Private->HardwareNeedsStarting) {
117 return EFI_NOT_STARTED;
118 }
119
120 if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
121 return EFI_INVALID_PARAMETER;
122 }
123
124 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
125 if (*Info == NULL) {
126 return EFI_OUT_OF_RESOURCES;
127 }
128
129 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
130
131 ModeData = &Private->ModeData[ModeNumber];
132 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
133 (*Info)->VerticalResolution = ModeData->VerticalResolution;
134 QemuVideoCompleteModeInfo (ModeData, *Info);
135
136 return EFI_SUCCESS;
137 }
138
139 EFI_STATUS
140 EFIAPI
141 QemuVideoGraphicsOutputSetMode (
142 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
143 IN UINT32 ModeNumber
144 )
145 /*++
146
147 Routine Description:
148
149 Graphics Output protocol interface to set video mode
150
151 Arguments:
152 This - Protocol instance pointer.
153 ModeNumber - The mode number to be set.
154
155 Returns:
156 EFI_SUCCESS - Graphics mode was changed.
157 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
158 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
159
160 --*/
161 {
162 QEMU_VIDEO_PRIVATE_DATA *Private;
163 QEMU_VIDEO_MODE_DATA *ModeData;
164 // UINTN Count;
165
166 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
167
168 if (ModeNumber >= This->Mode->MaxMode) {
169 return EFI_UNSUPPORTED;
170 }
171
172 ModeData = &Private->ModeData[ModeNumber];
173
174 if (Private->LineBuffer) {
175 gBS->FreePool (Private->LineBuffer);
176 }
177
178 Private->LineBuffer = NULL;
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 Status = gBS->AllocatePool (
324 EfiBootServicesData,
325 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
326 (VOID **) &Private->GraphicsOutput.Mode->Info
327 );
328 if (EFI_ERROR (Status)) {
329 return Status;
330 }
331 Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;
332 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
333 Private->HardwareNeedsStarting = TRUE;
334 Private->LineBuffer = NULL;
335
336 //
337 // Initialize the hardware
338 //
339 GraphicsOutput->SetMode (GraphicsOutput, 0);
340 DrawLogo (
341 Private,
342 Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,
343 Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution
344 );
345
346 return EFI_SUCCESS;
347 }
348
349 EFI_STATUS
350 QemuVideoGraphicsOutputDestructor (
351 QEMU_VIDEO_PRIVATE_DATA *Private
352 )
353 /*++
354
355 Routine Description:
356
357 Arguments:
358
359 Returns:
360
361 None
362
363 --*/
364 {
365 if (Private->GraphicsOutput.Mode != NULL) {
366 if (Private->GraphicsOutput.Mode->Info != NULL) {
367 gBS->FreePool (Private->GraphicsOutput.Mode->Info);
368 }
369 gBS->FreePool (Private->GraphicsOutput.Mode);
370 }
371
372 return EFI_SUCCESS;
373 }
374
375