VirtualBox

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

Last change on this file since 52069 was 52069, checked in by vboxsync, 11 years ago

Devices/EFI: fix a number of typos and copy/paste leftovers, should not change functionality in any way

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.3 KB
Line 
1/* $Id: VBoxVgaGraphicsOutput.c 52069 2014-07-17 08:40:36Z vboxsync $ */
2/** @file
3 * VBoxVgaGraphicsOutput.c
4 */
5
6/*
7 * Copyright (C) 2009-2012 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 = (UINTN)(FrameBufDesc->AddrRangeMax - FrameBufDesc->AddrRangeMin);
89
90 return EFI_SUCCESS;
91}
92
93
94//
95// Graphics Output Protocol Member Functions
96//
97EFI_STATUS
98EFIAPI
99VBoxVgaGraphicsOutputQueryMode (
100 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
101 IN UINT32 ModeNumber,
102 OUT UINTN *SizeOfInfo,
103 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
104 )
105/*++
106
107Routine Description:
108
109 Graphics Output protocol interface to query video mode
110
111 Arguments:
112 This - Protocol instance pointer.
113 ModeNumber - The mode number to return information on.
114 Info - Caller allocated buffer that returns information about ModeNumber.
115 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
116
117 Returns:
118 EFI_SUCCESS - Mode information returned.
119 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
120 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
121 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
122 EFI_INVALID_PARAMETER - One of the input args was NULL.
123
124--*/
125{
126 VBOX_VGA_PRIVATE_DATA *Private;
127
128 Private = VBOX_VGA_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
129
130 if (Private->HardwareNeedsStarting) {
131 return EFI_NOT_STARTED;
132 }
133
134 if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
135 return EFI_INVALID_PARAMETER;
136 }
137
138 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
139 if (*Info == NULL) {
140 return EFI_OUT_OF_RESOURCES;
141 }
142
143 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
144
145 (*Info)->HorizontalResolution = Private->ModeData[ModeNumber].HorizontalResolution;
146 (*Info)->VerticalResolution = Private->ModeData[ModeNumber].VerticalResolution;
147 VBoxVgaCompleteModeInfo (*Info);
148
149 return EFI_SUCCESS;
150}
151
152EFI_STATUS
153EFIAPI
154VBoxVgaGraphicsOutputSetMode (
155 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
156 IN UINT32 ModeNumber
157 )
158/*++
159
160Routine Description:
161
162 Graphics Output protocol interface to set video mode
163
164 Arguments:
165 This - Protocol instance pointer.
166 ModeNumber - The mode number to be set.
167
168 Returns:
169 EFI_SUCCESS - Graphics mode was changed.
170 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
171 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
172
173--*/
174{
175 VBOX_VGA_PRIVATE_DATA *Private;
176 VBOX_VGA_MODE_DATA *ModeData;
177
178 Private = VBOX_VGA_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
179
180 DEBUG((DEBUG_INFO, "%a:%d mode:%d\n", __FILE__, __LINE__, ModeNumber));
181 if (ModeNumber >= This->Mode->MaxMode) {
182 return EFI_UNSUPPORTED;
183 }
184
185 ModeData = &Private->ModeData[ModeNumber];
186
187 if (Private->LineBuffer) {
188 gBS->FreePool (Private->LineBuffer);
189 }
190
191 Private->LineBuffer = NULL;
192 Private->LineBuffer = AllocatePool (ModeData->HorizontalResolution * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
193 if (Private->LineBuffer == NULL) {
194 return EFI_OUT_OF_RESOURCES;
195 }
196
197 InitializeGraphicsMode (Private, &VBoxVgaVideoModes[ModeData->ModeNumber]);
198 if (Private->TmpBuf)
199 FreePool(Private->TmpBuf);
200 Private->TmpBuf = AllocatePool(ModeData->HorizontalResolution * ModeData->VerticalResolution * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
201 ASSERT(( Private->TmpBuf));
202
203 This->Mode->Mode = ModeNumber;
204 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
205 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
206 This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
207
208 VBoxVgaCompleteModeData (Private, This->Mode);
209
210 Private->HardwareNeedsStarting = FALSE;
211 /* update current mode */
212 Private->CurrentMode = ModeNumber;
213
214 return EFI_SUCCESS;
215}
216
217EFI_STATUS
218EFIAPI
219VBoxVgaGraphicsOutputBlt (
220 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
221 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
222 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
223 IN UINTN SourceX,
224 IN UINTN SourceY,
225 IN UINTN DestinationX,
226 IN UINTN DestinationY,
227 IN UINTN Width,
228 IN UINTN Height,
229 IN UINTN Delta
230 )
231/*++
232
233Routine Description:
234
235 Graphics Output protocol instance to block transfer for CirrusLogic device
236
237Arguments:
238
239 This - Pointer to Graphics Output protocol instance
240 BltBuffer - The data to transfer to screen
241 BltOperation - The operation to perform
242 SourceX - The X coordinate of the source for BltOperation
243 SourceY - The Y coordinate of the source for BltOperation
244 DestinationX - The X coordinate of the destination for BltOperation
245 DestinationY - The Y coordinate of the destination for BltOperation
246 Width - The width of a rectangle in the blt rectangle in pixels
247 Height - The height of a rectangle in the blt rectangle in pixels
248 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
249 If a Delta of 0 is used, the entire BltBuffer will be operated on.
250 If a subrectangle of the BltBuffer is used, then Delta represents
251 the number of bytes in a row of the BltBuffer.
252
253Returns:
254
255 EFI_INVALID_PARAMETER - Invalid parameter passed in
256 EFI_SUCCESS - Blt operation success
257
258--*/
259{
260 VBOX_VGA_PRIVATE_DATA *Private;
261 EFI_TPL OriginalTPL;
262 UINTN DstY;
263 UINTN SrcY;
264 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
265 UINTN X;
266 UINTN ScreenWidth;
267 UINTN Offset;
268 UINTN SourceOffset;
269 UINT32 CurrentMode;
270 EFI_STATUS Status;
271 UINTN ScreenHeight;
272
273 Private = VBOX_VGA_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
274
275 if ((BltOperation < 0) || (BltOperation >= EfiGraphicsOutputBltOperationMax)) {
276 return EFI_INVALID_PARAMETER;
277 }
278 if (Width == 0 || Height == 0) {
279 return EFI_INVALID_PARAMETER;
280 }
281
282 //
283 // If Delta is zero, then the entire BltBuffer is being used, so Delta
284 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
285 // the number of bytes in each row can be computed.
286 //
287 /* vvl: Delta passed in bytes to use it for coordinate arithmetic
288 we need convert it to pixels value.
289 */
290 if (Delta == 0) {
291 Delta = Width * 4;
292 }
293 Delta /= 4;
294
295 //
296 // We need to fill the Virtual Screen buffer with the blt data.
297 // The virtual screen is upside down, as the first row is the bootom row of
298 // the image.
299 //
300
301 CurrentMode = This->Mode->Mode;
302 //
303 // Make sure the SourceX, SourceY, DestinationX, DestinationY, Width, and Height parameters
304 // are valid for the operation and the current screen geometry.
305 //
306 if (BltOperation == EfiBltVideoToBltBuffer) {
307 //
308 // Video to BltBuffer: Source is Video, destination is BltBuffer
309 //
310 if (SourceY + Height > Private->ModeData[CurrentMode].VerticalResolution) {
311 return EFI_INVALID_PARAMETER;
312 }
313
314 if (SourceX + Width > Private->ModeData[CurrentMode].HorizontalResolution) {
315 return EFI_INVALID_PARAMETER;
316 }
317 } else {
318 //
319 // BltBuffer to Video: Source is BltBuffer, destination is Video
320 //
321 if (DestinationY + Height > Private->ModeData[CurrentMode].VerticalResolution) {
322 return EFI_INVALID_PARAMETER;
323 }
324
325 if (DestinationX + Width > Private->ModeData[CurrentMode].HorizontalResolution) {
326 return EFI_INVALID_PARAMETER;
327 }
328 }
329 //
330 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
331 // We would not want a timer based event (Cursor, ...) to come in while we are
332 // doing this operation.
333 //
334 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
335
336 switch (BltOperation) {
337 case EfiBltVideoToBltBuffer:
338 //
339 // Video to BltBuffer: Source is Video, destination is BltBuffer
340 //
341 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY) && BltBuffer; SrcY++, DstY++) {
342
343 Offset = (SrcY * Private->ModeData[CurrentMode].HorizontalResolution) + SourceX;
344 Status = Private->PciIo->Mem.Read (
345 Private->PciIo,
346 EfiPciIoWidthUint32,
347 0,
348 Offset * 4,
349 Width,
350 Private->LineBuffer
351 );
352 ASSERT_EFI_ERROR((Status));
353
354 for (X = 0; X < Width; X++) {
355 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltBuffer + (DstY * Delta) + (DestinationX + X);
356 *(UINT32 *)Blt = Private->LineBuffer[X];
357 }
358 }
359 break;
360
361 case EfiBltVideoToVideo:
362 //
363 // Perform hardware acceleration for Video to Video operations
364 //
365 ScreenWidth = Private->ModeData[CurrentMode].HorizontalResolution;
366 ScreenHeight = Private->ModeData[CurrentMode].VerticalResolution;
367 SourceOffset = (SourceY * Private->ModeData[CurrentMode].HorizontalResolution) + (SourceX);
368 Offset = (DestinationY * Private->ModeData[CurrentMode].HorizontalResolution) + (DestinationX);
369 VBoxVgaGraphicsOutputBlt(This, (EFI_GRAPHICS_OUTPUT_BLT_PIXEL*)Private->TmpBuf, EfiBltVideoToBltBuffer, SourceX, SourceY, 0, 0, ScreenWidth - SourceX, ScreenHeight - SourceY, 0);
370 VBoxVgaGraphicsOutputBlt(This, (EFI_GRAPHICS_OUTPUT_BLT_PIXEL*)Private->TmpBuf, EfiBltBufferToVideo, 0, 0, DestinationX, DestinationY, ScreenWidth - SourceX, ScreenHeight - SourceY, 0);
371 break;
372
373 case EfiBltVideoFill:
374 Blt = BltBuffer;
375
376 if (DestinationX == 0 && Width == Private->ModeData[CurrentMode].HorizontalResolution) {
377 Offset = DestinationY * Private->ModeData[CurrentMode].HorizontalResolution;
378 Status = Private->PciIo->Mem.Write (
379 Private->PciIo,
380 EfiPciIoWidthFillUint32,
381 0,
382 Offset * 4,
383 (Width * Height),
384 Blt
385 );
386 ASSERT_EFI_ERROR((Status));
387 } else {
388 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
389 Offset = (DstY * Private->ModeData[CurrentMode].HorizontalResolution) + DestinationX;
390 Status = Private->PciIo->Mem.Write (
391 Private->PciIo,
392 EfiPciIoWidthFillUint32,
393 0,
394 Offset * 4,
395 Width,
396 Blt
397 );
398 ASSERT_EFI_ERROR((Status));
399 }
400 }
401 break;
402
403 case EfiBltBufferToVideo:
404 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
405
406 for (X = 0; X < Width; X++) {
407 Blt =
408 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (
409 (UINT32 *) BltBuffer +
410 (SrcY * Delta) +
411 ((SourceX + X) )
412 );
413 Private->LineBuffer[X] = *(UINT32 *)Blt;
414 }
415
416 Offset = (DstY * Private->ModeData[CurrentMode].HorizontalResolution) + DestinationX;
417
418 Status = Private->PciIo->Mem.Write (
419 Private->PciIo,
420 EfiPciIoWidthUint32,
421 0,
422 Offset * 4,
423 Width,
424 Private->LineBuffer
425 );
426 ASSERT_EFI_ERROR((Status));
427 }
428 break;
429 default:
430 ASSERT (FALSE);
431 }
432
433 gBS->RestoreTPL (OriginalTPL);
434
435 return EFI_SUCCESS;
436}
437
438EFI_STATUS
439VBoxVgaGraphicsOutputConstructor (
440 VBOX_VGA_PRIVATE_DATA *Private
441 )
442{
443 EFI_STATUS Status;
444 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
445
446
447 GraphicsOutput = &Private->GraphicsOutput;
448 GraphicsOutput->QueryMode = VBoxVgaGraphicsOutputQueryMode;
449 GraphicsOutput->SetMode = VBoxVgaGraphicsOutputSetMode;
450 GraphicsOutput->Blt = VBoxVgaGraphicsOutputBlt;
451
452 //
453 // Initialize the private data
454 //
455 Status = gBS->AllocatePool (
456 EfiBootServicesData,
457 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
458 (VOID **) &Private->GraphicsOutput.Mode
459 );
460 if (EFI_ERROR (Status)) {
461 return Status;
462 }
463 Status = gBS->AllocatePool (
464 EfiBootServicesData,
465 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
466 (VOID **) &Private->GraphicsOutput.Mode->Info
467 );
468 if (EFI_ERROR (Status)) {
469 return Status;
470 }
471 Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;
472 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
473 Private->HardwareNeedsStarting = TRUE;
474 Private->LineBuffer = NULL;
475
476 //
477 // Initialize the hardware
478 //
479 GraphicsOutput->SetMode (GraphicsOutput, 2);
480 DrawLogo (
481 Private,
482 Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,
483 Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution
484 );
485
486 return EFI_SUCCESS;
487}
488
489EFI_STATUS
490VBoxVgaGraphicsOutputDestructor (
491 VBOX_VGA_PRIVATE_DATA *Private
492 )
493/*++
494
495Routine Description:
496
497Arguments:
498
499Returns:
500
501 None
502
503--*/
504{
505 if (Private->GraphicsOutput.Mode != NULL) {
506 if (Private->GraphicsOutput.Mode->Info != NULL) {
507 gBS->FreePool (Private->GraphicsOutput.Mode->Info);
508 }
509 gBS->FreePool (Private->GraphicsOutput.Mode);
510 }
511
512 return EFI_SUCCESS;
513}
514
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