VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxVgaDxe/VBoxVgaGraphicsOutput.c@ 75851

Last change on this file since 75851 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.9 KB
Line 
1/* $Id: VBoxVgaGraphicsOutput.c 69500 2017-10-28 15:14:05Z vboxsync $ */
2/** @file
3 * VBoxVgaGraphicsOutput.c
4 */
5
6/*
7 * Copyright (C) 2009-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*
28 This code is based on:
29
30Copyright (c) 2007, Intel Corporation
31All rights reserved. This program and the accompanying materials
32are licensed and made available under the terms and conditions of the BSD License
33which accompanies this distribution. The full text of the license may be found at
34http://opensource.org/licenses/bsd-license.php
35
36THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
37WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
38
39Module Name:
40
41 UefiVBoxVgaGraphicsOutput.c
42
43Abstract:
44
45 This file produces the graphics abstraction of Graphics Output Protocol. It is called by
46 VBoxVga.c file which deals with the EFI 1.1 driver model.
47 This file just does graphics.
48
49*/
50#include "VBoxVga.h"
51#include <IndustryStandard/Acpi.h>
52
53
54STATIC
55VOID
56VBoxVgaCompleteModeInfo (
57 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info
58 )
59{
60 Info->Version = 0;
61 Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
62 Info->PixelsPerScanLine = Info->HorizontalResolution;
63}
64
65
66STATIC
67EFI_STATUS
68VBoxVgaCompleteModeData (
69 IN VBOX_VGA_PRIVATE_DATA *Private,
70 OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode
71 )
72{
73 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
74 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *FrameBufDesc;
75
76 Info = Mode->Info;
77 VBoxVgaCompleteModeInfo (Info);
78
79 Private->PciIo->GetBarAttributes (
80 Private->PciIo,
81 0,
82 NULL,
83 (VOID**) &FrameBufDesc
84 );
85
86 DEBUG((DEBUG_INFO, "%a:%d FrameBufferBase:%x\n", __FILE__, __LINE__, FrameBufDesc->AddrRangeMin));
87 Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin;
88 Mode->FrameBufferSize = Info->PixelsPerScanLine * Info->VerticalResolution
89 * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL); /* 32bpp only! */
90
91 return EFI_SUCCESS;
92}
93
94
95//
96// Graphics Output Protocol Member Functions
97//
98EFI_STATUS
99EFIAPI
100VBoxVgaGraphicsOutputQueryMode (
101 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
102 IN UINT32 ModeNumber,
103 OUT UINTN *SizeOfInfo,
104 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
105 )
106/*++
107
108Routine Description:
109
110 Graphics Output protocol interface to query video mode
111
112 Arguments:
113 This - Protocol instance pointer.
114 ModeNumber - The mode number to return information on.
115 Info - Caller allocated buffer that returns information about ModeNumber.
116 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
117
118 Returns:
119 EFI_SUCCESS - Mode information returned.
120 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
121 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
122 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
123 EFI_INVALID_PARAMETER - One of the input args was NULL.
124
125--*/
126{
127 VBOX_VGA_PRIVATE_DATA *Private;
128
129 Private = VBOX_VGA_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
130
131 if (Private->HardwareNeedsStarting) {
132 return EFI_NOT_STARTED;
133 }
134
135 if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
136 return EFI_INVALID_PARAMETER;
137 }
138
139 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
140 if (*Info == NULL) {
141 return EFI_OUT_OF_RESOURCES;
142 }
143
144 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
145
146 (*Info)->HorizontalResolution = Private->ModeData[ModeNumber].HorizontalResolution;
147 (*Info)->VerticalResolution = Private->ModeData[ModeNumber].VerticalResolution;
148 VBoxVgaCompleteModeInfo (*Info);
149
150 return EFI_SUCCESS;
151}
152
153EFI_STATUS
154EFIAPI
155VBoxVgaGraphicsOutputSetMode (
156 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
157 IN UINT32 ModeNumber
158 )
159/*++
160
161Routine Description:
162
163 Graphics Output protocol interface to set video mode
164
165 Arguments:
166 This - Protocol instance pointer.
167 ModeNumber - The mode number to be set.
168
169 Returns:
170 EFI_SUCCESS - Graphics mode was changed.
171 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
172 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
173
174--*/
175{
176 VBOX_VGA_PRIVATE_DATA *Private;
177 VBOX_VGA_MODE_DATA *ModeData;
178
179 Private = VBOX_VGA_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
180
181 DEBUG((DEBUG_INFO, "%a:%d mode:%d\n", __FILE__, __LINE__, ModeNumber));
182 if (ModeNumber >= This->Mode->MaxMode) {
183 return EFI_UNSUPPORTED;
184 }
185
186 ModeData = &Private->ModeData[ModeNumber];
187
188 InitializeGraphicsMode (Private, &VBoxVgaVideoModes[ModeData->ModeNumber]);
189
190 This->Mode->Mode = ModeNumber;
191 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
192 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
193 This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
194
195 VBoxVgaCompleteModeData (Private, This->Mode);
196
197 Private->HardwareNeedsStarting = FALSE;
198 /* update current mode */
199 Private->CurrentMode = ModeNumber;
200
201 return EFI_SUCCESS;
202}
203
204EFI_STATUS
205EFIAPI
206VBoxVgaGraphicsOutputBlt (
207 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
208 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
209 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
210 IN UINTN SourceX,
211 IN UINTN SourceY,
212 IN UINTN DestinationX,
213 IN UINTN DestinationY,
214 IN UINTN Width,
215 IN UINTN Height,
216 IN UINTN Delta
217 )
218/*++
219
220Routine Description:
221
222 Graphics Output protocol instance to block transfer for CirrusLogic device
223
224Arguments:
225
226 This - Pointer to Graphics Output protocol instance
227 BltBuffer - The data to transfer to screen
228 BltOperation - The operation to perform
229 SourceX - The X coordinate of the source for BltOperation
230 SourceY - The Y coordinate of the source for BltOperation
231 DestinationX - The X coordinate of the destination for BltOperation
232 DestinationY - The Y coordinate of the destination for BltOperation
233 Width - The width of a rectangle in the blt rectangle in pixels
234 Height - The height of a rectangle in the blt rectangle in pixels
235 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
236 If a Delta of 0 is used, the entire BltBuffer will be operated on.
237 If a subrectangle of the BltBuffer is used, then Delta represents
238 the number of bytes in a row of the BltBuffer.
239
240Returns:
241
242 EFI_INVALID_PARAMETER - Invalid parameter passed in
243 EFI_SUCCESS - Blt operation success
244
245--*/
246{
247 VBOX_VGA_PRIVATE_DATA *Private;
248 EFI_TPL OriginalTPL;
249 UINTN DstY;
250 UINTN SrcY;
251 UINT32 CurrentMode;
252 UINTN ScreenWidth;
253 UINTN ScreenHeight;
254 EFI_STATUS Status;
255
256 Private = VBOX_VGA_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
257 CurrentMode = This->Mode->Mode;
258 ScreenWidth = Private->ModeData[CurrentMode].HorizontalResolution;
259 ScreenHeight = Private->ModeData[CurrentMode].VerticalResolution;
260
261 if ((BltOperation < 0) || (BltOperation >= EfiGraphicsOutputBltOperationMax)) {
262 return EFI_INVALID_PARAMETER;
263 }
264 if (Width == 0 || Height == 0) {
265 return EFI_INVALID_PARAMETER;
266 }
267
268 //
269 // If Delta is zero, then the entire BltBuffer is being used, so Delta
270 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
271 // the number of bytes in each row can be computed.
272 //
273 if (Delta == 0) {
274 Delta = Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
275 }
276 // code below assumes a Delta value in pixels, not bytes
277 Delta /= sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
278
279 //
280 // Make sure the SourceX, SourceY, DestinationX, DestinationY, Width, and Height parameters
281 // are valid for the operation and the current screen geometry.
282 //
283 if (BltOperation == EfiBltVideoToBltBuffer || BltOperation == EfiBltVideoToVideo) {
284 if (SourceY + Height > ScreenHeight) {
285 return EFI_INVALID_PARAMETER;
286 }
287
288 if (SourceX + Width > ScreenWidth) {
289 return EFI_INVALID_PARAMETER;
290 }
291 }
292 if (BltOperation == EfiBltBufferToVideo || BltOperation == EfiBltVideoToVideo || BltOperation == EfiBltVideoFill) {
293 if (DestinationY + Height > ScreenHeight) {
294 return EFI_INVALID_PARAMETER;
295 }
296
297 if (DestinationX + Width > ScreenWidth) {
298 return EFI_INVALID_PARAMETER;
299 }
300 }
301
302 //
303 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
304 // We would not want a timer based event (Cursor, ...) to come in while we are
305 // doing this operation.
306 //
307 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
308
309 switch (BltOperation) {
310 case EfiBltVideoToBltBuffer:
311 //
312 // Video to BltBuffer: Source is Video, destination is BltBuffer
313 //
314 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY) && BltBuffer; SrcY++, DstY++) {
315 /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthUint32) and format matches EFI_GRAPHICS_OUTPUT_BLT_PIXEL
316 Status = Private->PciIo->Mem.Read (
317 Private->PciIo,
318 EfiPciIoWidthUint32,
319 0,
320 ((SrcY * ScreenWidth) + SourceX) * 4,
321 Width,
322 BltBuffer + (DstY * Delta) + DestinationX
323 );
324 ASSERT_EFI_ERROR((Status));
325 }
326 break;
327
328 case EfiBltBufferToVideo:
329 //
330 // BltBuffer to Video: Source is BltBuffer, destination is Video
331 //
332 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
333 /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthUint32) and format matches EFI_GRAPHICS_OUTPUT_BLT_PIXEL
334 Status = Private->PciIo->Mem.Write (
335 Private->PciIo,
336 EfiPciIoWidthUint32,
337 0,
338 ((DstY * ScreenWidth) + DestinationX) * 4,
339 Width,
340 BltBuffer + (SrcY * Delta) + SourceX
341 );
342 ASSERT_EFI_ERROR((Status));
343 }
344 break;
345
346 case EfiBltVideoToVideo:
347 //
348 // Video to Video: Source is Video, destination is Video
349 //
350 if (DestinationY <= SourceY) {
351 // forward copy
352 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
353 /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthUint32) and format matches EFI_GRAPHICS_OUTPUT_BLT_PIXEL
354 Status = Private->PciIo->CopyMem (
355 Private->PciIo,
356 EfiPciIoWidthUint32,
357 0,
358 ((DstY * ScreenWidth) + DestinationX) * 4,
359 0,
360 ((SrcY * ScreenWidth) + SourceX) * 4,
361 Width
362 );
363 ASSERT_EFI_ERROR((Status));
364 }
365 } else {
366 // reverse copy
367 for (SrcY = SourceY + Height - 1, DstY = DestinationY + Height - 1; SrcY >= SourceY && SrcY <= SourceY + Height - 1; SrcY--, DstY--) {
368 /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthUint32) and format matches EFI_GRAPHICS_OUTPUT_BLT_PIXEL
369 Status = Private->PciIo->CopyMem (
370 Private->PciIo,
371 EfiPciIoWidthUint32,
372 0,
373 ((DstY * ScreenWidth) + DestinationX) * 4,
374 0,
375 ((SrcY * ScreenWidth) + SourceX) * 4,
376 Width
377 );
378 ASSERT_EFI_ERROR((Status));
379 }
380 }
381 break;
382
383 case EfiBltVideoFill:
384 //
385 // Video Fill: Source is BltBuffer, destination is Video
386 //
387 if (DestinationX == 0 && Width == ScreenWidth) {
388 /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthFillUint32) and format matches EFI_GRAPHICS_OUTPUT_BLT_PIXEL
389 Status = Private->PciIo->Mem.Write (
390 Private->PciIo,
391 EfiPciIoWidthFillUint32,
392 0,
393 DestinationY * ScreenWidth * 4,
394 (Width * Height),
395 BltBuffer
396 );
397 ASSERT_EFI_ERROR((Status));
398 } else {
399 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
400 /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthFillUint32) and format matches EFI_GRAPHICS_OUTPUT_BLT_PIXEL
401 Status = Private->PciIo->Mem.Write (
402 Private->PciIo,
403 EfiPciIoWidthFillUint32,
404 0,
405 ((DstY * ScreenWidth) + DestinationX) * 4,
406 Width,
407 BltBuffer
408 );
409 ASSERT_EFI_ERROR((Status));
410 }
411 }
412 break;
413
414 default:
415 ASSERT (FALSE);
416 }
417
418 gBS->RestoreTPL (OriginalTPL);
419
420 return EFI_SUCCESS;
421}
422
423EFI_STATUS
424VBoxVgaGraphicsOutputConstructor (
425 VBOX_VGA_PRIVATE_DATA *Private
426 )
427{
428 EFI_STATUS Status;
429 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
430 UINT32 Index;
431 UINT32 HorizontalResolution = 1024;
432 UINT32 VerticalResolution = 768;
433 UINT32 ColorDepth = 32;
434
435 DEBUG((DEBUG_INFO, "%a:%d construct\n", __FILE__, __LINE__));
436
437 GraphicsOutput = &Private->GraphicsOutput;
438 GraphicsOutput->QueryMode = VBoxVgaGraphicsOutputQueryMode;
439 GraphicsOutput->SetMode = VBoxVgaGraphicsOutputSetMode;
440 GraphicsOutput->Blt = VBoxVgaGraphicsOutputBlt;
441
442 //
443 // Initialize the private data
444 //
445 Status = gBS->AllocatePool (
446 EfiBootServicesData,
447 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
448 (VOID **) &Private->GraphicsOutput.Mode
449 );
450 if (EFI_ERROR (Status)) {
451 return Status;
452 }
453 Status = gBS->AllocatePool (
454 EfiBootServicesData,
455 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
456 (VOID **) &Private->GraphicsOutput.Mode->Info
457 );
458 if (EFI_ERROR (Status)) {
459 return Status;
460 }
461 Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;
462 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
463 Private->HardwareNeedsStarting = TRUE;
464
465 //
466 // Initialize the hardware
467 //
468 VBoxVgaGetVmVariable(EFI_INFO_INDEX_HORIZONTAL_RESOLUTION, (CHAR8 *)&HorizontalResolution,
469 sizeof(HorizontalResolution));
470 VBoxVgaGetVmVariable(EFI_INFO_INDEX_VERTICAL_RESOLUTION, (CHAR8 *)&VerticalResolution,
471 sizeof(VerticalResolution));
472 for (Index = 0; Index < Private->MaxMode; Index++)
473 {
474 if ( HorizontalResolution == Private->ModeData[Index].HorizontalResolution
475 && VerticalResolution == Private->ModeData[Index].VerticalResolution
476 && ColorDepth == Private->ModeData[Index].ColorDepth)
477 break;
478 }
479 // not found? try mode number
480 if (Index >= Private->MaxMode)
481 {
482 VBoxVgaGetVmVariable(EFI_INFO_INDEX_GRAPHICS_MODE, (CHAR8 *)&Index, sizeof(Index));
483 // try with mode 2 (usually 1024x768) as a fallback
484 if (Index >= Private->MaxMode)
485 Index = 2;
486 // try with mode 0 (usually 640x480) as a fallback
487 if (Index >= Private->MaxMode)
488 Index = 0;
489 }
490
491 // skip mode setting completely if there is no valid mode
492 if (Index >= Private->MaxMode)
493 return EFI_UNSUPPORTED;
494
495 GraphicsOutput->SetMode (GraphicsOutput, Index);
496
497 DrawLogo (
498 Private,
499 Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,
500 Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution
501 );
502
503 PcdSet32(PcdVideoHorizontalResolution, Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution);
504 PcdSet32(PcdVideoVerticalResolution, Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution);
505
506 return EFI_SUCCESS;
507}
508
509EFI_STATUS
510VBoxVgaGraphicsOutputDestructor (
511 VBOX_VGA_PRIVATE_DATA *Private
512 )
513/*++
514
515Routine Description:
516
517Arguments:
518
519Returns:
520
521 None
522
523--*/
524{
525 if (Private->GraphicsOutput.Mode != NULL) {
526 if (Private->GraphicsOutput.Mode->Info != NULL) {
527 gBS->FreePool (Private->GraphicsOutput.Mode->Info);
528 }
529 gBS->FreePool (Private->GraphicsOutput.Mode);
530 }
531
532 return EFI_SUCCESS;
533}
534
Note: See TracBrowser for help on using the repository browser.

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