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