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