VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/OvmfPkg/QemuVideoDxe/Gop.c

Last change on this file was 108794, checked in by vboxsync, 4 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette