]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/QemuVideoDxe/Gop.c
OvmfPkg: Add QemuVideoDxe driver
[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 InitializeGraphicsMode (Private, &QemuVideoVideoModes[ModeData->ModeNumber]);
185
186 This->Mode->Mode = ModeNumber;
187 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
188 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
189 This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
190
191 QemuVideoCompleteModeData (Private, This->Mode);
192
193 BltLibConfigure (
194 (VOID*)(UINTN) This->Mode->FrameBufferBase,
195 This->Mode->Info
196 );
197
198 Private->HardwareNeedsStarting = FALSE;
199
200 return EFI_SUCCESS;
201 }
202
203 EFI_STATUS
204 EFIAPI
205 QemuVideoGraphicsOutputBlt (
206 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
207 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
208 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
209 IN UINTN SourceX,
210 IN UINTN SourceY,
211 IN UINTN DestinationX,
212 IN UINTN DestinationY,
213 IN UINTN Width,
214 IN UINTN Height,
215 IN UINTN Delta
216 )
217 /*++
218
219 Routine Description:
220
221 Graphics Output protocol instance to block transfer for CirrusLogic device
222
223 Arguments:
224
225 This - Pointer to Graphics Output protocol instance
226 BltBuffer - The data to transfer to screen
227 BltOperation - The operation to perform
228 SourceX - The X coordinate of the source for BltOperation
229 SourceY - The Y coordinate of the source for BltOperation
230 DestinationX - The X coordinate of the destination for BltOperation
231 DestinationY - The Y coordinate of the destination for BltOperation
232 Width - The width of a rectangle in the blt rectangle in pixels
233 Height - The height of a rectangle in the blt rectangle in pixels
234 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
235 If a Delta of 0 is used, the entire BltBuffer will be operated on.
236 If a subrectangle of the BltBuffer is used, then Delta represents
237 the number of bytes in a row of the BltBuffer.
238
239 Returns:
240
241 EFI_INVALID_PARAMETER - Invalid parameter passed in
242 EFI_SUCCESS - Blt operation success
243
244 --*/
245 {
246 EFI_STATUS Status;
247 EFI_TPL OriginalTPL;
248
249 //
250 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
251 // We would not want a timer based event (Cursor, ...) to come in while we are
252 // doing this operation.
253 //
254 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
255
256 switch (BltOperation) {
257 case EfiBltVideoToBltBuffer:
258 case EfiBltBufferToVideo:
259 case EfiBltVideoFill:
260 case EfiBltVideoToVideo:
261 Status = BltLibGopBlt (
262 BltBuffer,
263 BltOperation,
264 SourceX,
265 SourceY,
266 DestinationX,
267 DestinationY,
268 Width,
269 Height,
270 Delta
271 );
272 break;
273
274 default:
275 Status = EFI_INVALID_PARAMETER;
276 ASSERT (FALSE);
277 }
278
279 gBS->RestoreTPL (OriginalTPL);
280
281 return Status;
282 }
283
284 EFI_STATUS
285 QemuVideoGraphicsOutputConstructor (
286 QEMU_VIDEO_PRIVATE_DATA *Private
287 )
288 {
289 EFI_STATUS Status;
290 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
291
292
293 GraphicsOutput = &Private->GraphicsOutput;
294 GraphicsOutput->QueryMode = QemuVideoGraphicsOutputQueryMode;
295 GraphicsOutput->SetMode = QemuVideoGraphicsOutputSetMode;
296 GraphicsOutput->Blt = QemuVideoGraphicsOutputBlt;
297
298 //
299 // Initialize the private data
300 //
301 Status = gBS->AllocatePool (
302 EfiBootServicesData,
303 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
304 (VOID **) &Private->GraphicsOutput.Mode
305 );
306 if (EFI_ERROR (Status)) {
307 return Status;
308 }
309 Status = gBS->AllocatePool (
310 EfiBootServicesData,
311 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
312 (VOID **) &Private->GraphicsOutput.Mode->Info
313 );
314 if (EFI_ERROR (Status)) {
315 return Status;
316 }
317 Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;
318 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
319 Private->HardwareNeedsStarting = TRUE;
320 Private->LineBuffer = NULL;
321
322 //
323 // Initialize the hardware
324 //
325 GraphicsOutput->SetMode (GraphicsOutput, 0);
326 DrawLogo (
327 Private,
328 Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,
329 Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution
330 );
331
332 return EFI_SUCCESS;
333 }
334
335 EFI_STATUS
336 QemuVideoGraphicsOutputDestructor (
337 QEMU_VIDEO_PRIVATE_DATA *Private
338 )
339 /*++
340
341 Routine Description:
342
343 Arguments:
344
345 Returns:
346
347 None
348
349 --*/
350 {
351 if (Private->GraphicsOutput.Mode != NULL) {
352 if (Private->GraphicsOutput.Mode->Info != NULL) {
353 gBS->FreePool (Private->GraphicsOutput.Mode->Info);
354 }
355 gBS->FreePool (Private->GraphicsOutput.Mode);
356 }
357
358 return EFI_SUCCESS;
359 }
360
361