]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/QemuVideoDxe/Gop.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / QemuVideoDxe / Gop.c
1 /** @file
2 Graphics Output Protocol functions for the QEMU video controller.
3
4 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "Qemu.h"
11
12 STATIC
13 VOID
14 QemuVideoCompleteModeInfo (
15 IN QEMU_VIDEO_MODE_DATA *ModeData,
16 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info
17 )
18 {
19 Info->Version = 0;
20 if (ModeData->ColorDepth == 8) {
21 Info->PixelFormat = PixelBitMask;
22 Info->PixelInformation.RedMask = PIXEL_RED_MASK;
23 Info->PixelInformation.GreenMask = PIXEL_GREEN_MASK;
24 Info->PixelInformation.BlueMask = PIXEL_BLUE_MASK;
25 Info->PixelInformation.ReservedMask = 0;
26 } else if (ModeData->ColorDepth == 24) {
27 Info->PixelFormat = PixelBitMask;
28 Info->PixelInformation.RedMask = PIXEL24_RED_MASK;
29 Info->PixelInformation.GreenMask = PIXEL24_GREEN_MASK;
30 Info->PixelInformation.BlueMask = PIXEL24_BLUE_MASK;
31 Info->PixelInformation.ReservedMask = 0;
32 } else if (ModeData->ColorDepth == 32) {
33 DEBUG ((DEBUG_INFO, "PixelBlueGreenRedReserved8BitPerColor\n"));
34 Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
35 }
36
37 Info->PixelsPerScanLine = Info->HorizontalResolution;
38 }
39
40 STATIC
41 EFI_STATUS
42 QemuVideoCompleteModeData (
43 IN QEMU_VIDEO_PRIVATE_DATA *Private,
44 OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode
45 )
46 {
47 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
48 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *FrameBufDesc;
49 QEMU_VIDEO_MODE_DATA *ModeData;
50
51 ModeData = &Private->ModeData[Mode->Mode];
52 Info = Mode->Info;
53 QemuVideoCompleteModeInfo (ModeData, Info);
54
55 Private->PciIo->GetBarAttributes (
56 Private->PciIo,
57 Private->FrameBufferVramBarIndex,
58 NULL,
59 (VOID **)&FrameBufDesc
60 );
61
62 Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin;
63 Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution;
64 Mode->FrameBufferSize = Mode->FrameBufferSize * ((ModeData->ColorDepth + 7) / 8);
65 Mode->FrameBufferSize = EFI_PAGES_TO_SIZE (
66 EFI_SIZE_TO_PAGES (Mode->FrameBufferSize)
67 );
68 DEBUG ((
69 DEBUG_INFO,
70 "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n",
71 Mode->FrameBufferBase,
72 (UINT64)Mode->FrameBufferSize
73 ));
74
75 FreePool (FrameBufDesc);
76 return EFI_SUCCESS;
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
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 ((Info == NULL) || (SizeOfInfo == NULL) || (ModeNumber >= This->Mode->MaxMode)) {
118 return EFI_INVALID_PARAMETER;
119 }
120
121 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
122 if (*Info == NULL) {
123 return EFI_OUT_OF_RESOURCES;
124 }
125
126 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
127
128 ModeData = &Private->ModeData[ModeNumber];
129 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
130 (*Info)->VerticalResolution = ModeData->VerticalResolution;
131 QemuVideoCompleteModeInfo (ModeData, *Info);
132
133 return EFI_SUCCESS;
134 }
135
136 EFI_STATUS
137 EFIAPI
138 QemuVideoGraphicsOutputSetMode (
139 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
140 IN UINT32 ModeNumber
141 )
142
143 /*++
144
145 Routine Description:
146
147 Graphics Output protocol interface to set video mode
148
149 Arguments:
150 This - Protocol instance pointer.
151 ModeNumber - The mode number to be set.
152
153 Returns:
154 EFI_SUCCESS - Graphics mode was changed.
155 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
156 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
157
158 --*/
159 {
160 QEMU_VIDEO_PRIVATE_DATA *Private;
161 QEMU_VIDEO_MODE_DATA *ModeData;
162 RETURN_STATUS Status;
163 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black;
164
165 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
166
167 if (ModeNumber >= This->Mode->MaxMode) {
168 return EFI_UNSUPPORTED;
169 }
170
171 ModeData = &Private->ModeData[ModeNumber];
172
173 switch (Private->Variant) {
174 case QEMU_VIDEO_CIRRUS_5430:
175 case QEMU_VIDEO_CIRRUS_5446:
176 InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]);
177 break;
178 case QEMU_VIDEO_BOCHS_MMIO:
179 case QEMU_VIDEO_BOCHS:
180 InitializeBochsGraphicsMode (Private, ModeData);
181 break;
182 default:
183 ASSERT (FALSE);
184 return EFI_DEVICE_ERROR;
185 }
186
187 This->Mode->Mode = ModeNumber;
188 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
189 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
190 This->Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
191
192 QemuVideoCompleteModeData (Private, This->Mode);
193
194 //
195 // Re-initialize the frame buffer configure when mode changes.
196 //
197 Status = FrameBufferBltConfigure (
198 (VOID *)(UINTN)This->Mode->FrameBufferBase,
199 This->Mode->Info,
200 Private->FrameBufferBltConfigure,
201 &Private->FrameBufferBltConfigureSize
202 );
203 if (Status == RETURN_BUFFER_TOO_SMALL) {
204 //
205 // Frame buffer configure may be larger in new mode.
206 //
207 if (Private->FrameBufferBltConfigure != NULL) {
208 FreePool (Private->FrameBufferBltConfigure);
209 }
210
211 Private->FrameBufferBltConfigure =
212 AllocatePool (Private->FrameBufferBltConfigureSize);
213 ASSERT (Private->FrameBufferBltConfigure != NULL);
214
215 //
216 // Create the configuration for FrameBufferBltLib
217 //
218 Status = FrameBufferBltConfigure (
219 (VOID *)(UINTN)This->Mode->FrameBufferBase,
220 This->Mode->Info,
221 Private->FrameBufferBltConfigure,
222 &Private->FrameBufferBltConfigureSize
223 );
224 }
225
226 ASSERT (Status == RETURN_SUCCESS);
227
228 //
229 // Per UEFI Spec, need to clear the visible portions of the output display to black.
230 //
231 ZeroMem (&Black, sizeof (Black));
232 Status = FrameBufferBlt (
233 Private->FrameBufferBltConfigure,
234 &Black,
235 EfiBltVideoFill,
236 0,
237 0,
238 0,
239 0,
240 This->Mode->Info->HorizontalResolution,
241 This->Mode->Info->VerticalResolution,
242 0
243 );
244 ASSERT_RETURN_ERROR (Status);
245
246 return EFI_SUCCESS;
247 }
248
249 EFI_STATUS
250 EFIAPI
251 QemuVideoGraphicsOutputBlt (
252 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
253 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,
254 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
255 IN UINTN SourceX,
256 IN UINTN SourceY,
257 IN UINTN DestinationX,
258 IN UINTN DestinationY,
259 IN UINTN Width,
260 IN UINTN Height,
261 IN UINTN Delta
262 )
263
264 /*++
265
266 Routine Description:
267
268 Graphics Output protocol instance to block transfer for CirrusLogic device
269
270 Arguments:
271
272 This - Pointer to Graphics Output protocol instance
273 BltBuffer - The data to transfer to screen
274 BltOperation - The operation to perform
275 SourceX - The X coordinate of the source for BltOperation
276 SourceY - The Y coordinate of the source for BltOperation
277 DestinationX - The X coordinate of the destination for BltOperation
278 DestinationY - The Y coordinate of the destination for BltOperation
279 Width - The width of a rectangle in the blt rectangle in pixels
280 Height - The height of a rectangle in the blt rectangle in pixels
281 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
282 If a Delta of 0 is used, the entire BltBuffer will be operated on.
283 If a subrectangle of the BltBuffer is used, then Delta represents
284 the number of bytes in a row of the BltBuffer.
285
286 Returns:
287
288 EFI_INVALID_PARAMETER - Invalid parameter passed in
289 EFI_SUCCESS - Blt operation success
290
291 --*/
292 {
293 EFI_STATUS Status;
294 EFI_TPL OriginalTPL;
295 QEMU_VIDEO_PRIVATE_DATA *Private;
296
297 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
298 //
299 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
300 // We would not want a timer based event (Cursor, ...) to come in while we are
301 // doing this operation.
302 //
303 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
304
305 switch (BltOperation) {
306 case EfiBltVideoToBltBuffer:
307 case EfiBltBufferToVideo:
308 case EfiBltVideoFill:
309 case EfiBltVideoToVideo:
310 Status = FrameBufferBlt (
311 Private->FrameBufferBltConfigure,
312 BltBuffer,
313 BltOperation,
314 SourceX,
315 SourceY,
316 DestinationX,
317 DestinationY,
318 Width,
319 Height,
320 Delta
321 );
322 break;
323
324 default:
325 Status = EFI_INVALID_PARAMETER;
326 break;
327 }
328
329 gBS->RestoreTPL (OriginalTPL);
330
331 return Status;
332 }
333
334 EFI_STATUS
335 QemuVideoGraphicsOutputConstructor (
336 QEMU_VIDEO_PRIVATE_DATA *Private
337 )
338 {
339 EFI_STATUS Status;
340 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
341
342 GraphicsOutput = &Private->GraphicsOutput;
343 GraphicsOutput->QueryMode = QemuVideoGraphicsOutputQueryMode;
344 GraphicsOutput->SetMode = QemuVideoGraphicsOutputSetMode;
345 GraphicsOutput->Blt = QemuVideoGraphicsOutputBlt;
346
347 //
348 // Initialize the private data
349 //
350 Status = gBS->AllocatePool (
351 EfiBootServicesData,
352 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
353 (VOID **)&Private->GraphicsOutput.Mode
354 );
355 if (EFI_ERROR (Status)) {
356 return Status;
357 }
358
359 Status = gBS->AllocatePool (
360 EfiBootServicesData,
361 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
362 (VOID **)&Private->GraphicsOutput.Mode->Info
363 );
364 if (EFI_ERROR (Status)) {
365 goto FreeMode;
366 }
367
368 Private->GraphicsOutput.Mode->MaxMode = (UINT32)Private->MaxMode;
369 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
370 Private->FrameBufferBltConfigure = NULL;
371 Private->FrameBufferBltConfigureSize = 0;
372
373 //
374 // Initialize the hardware
375 //
376 Status = GraphicsOutput->SetMode (GraphicsOutput, 0);
377 if (EFI_ERROR (Status)) {
378 goto FreeInfo;
379 }
380
381 DrawLogo (
382 Private,
383 Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,
384 Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution
385 );
386
387 return EFI_SUCCESS;
388
389 FreeInfo:
390 FreePool (Private->GraphicsOutput.Mode->Info);
391
392 FreeMode:
393 FreePool (Private->GraphicsOutput.Mode);
394 Private->GraphicsOutput.Mode = NULL;
395
396 return Status;
397 }
398
399 EFI_STATUS
400 QemuVideoGraphicsOutputDestructor (
401 QEMU_VIDEO_PRIVATE_DATA *Private
402 )
403
404 /*++
405
406 Routine Description:
407
408 Arguments:
409
410 Returns:
411
412 None
413
414 --*/
415 {
416 if (Private->FrameBufferBltConfigure != NULL) {
417 FreePool (Private->FrameBufferBltConfigure);
418 }
419
420 if (Private->GraphicsOutput.Mode != NULL) {
421 if (Private->GraphicsOutput.Mode->Info != NULL) {
422 gBS->FreePool (Private->GraphicsOutput.Mode->Info);
423 }
424
425 gBS->FreePool (Private->GraphicsOutput.Mode);
426 }
427
428 return EFI_SUCCESS;
429 }