VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/VBoxPkg/VmwSvga3Dxe/Gop.c@ 100688

Last change on this file since 100688 was 100688, checked in by vboxsync, 21 months ago

Device/EFI/Firmware/VmwSvga3Dxe: Implement enough of the VMware SVGA 3 interface to get a screen output during the UEFI phase, bugref:10490

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