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