VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware2/VBoxPkg/VBoxVgaDxe/VBoxVgaGraphicsOutput.c@ 33110

Last change on this file since 33110 was 29081, checked in by vboxsync, 15 years ago

more EFI exports to OSE

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