Gop.c revision cd1526101469cb639c7166c0b750c5ebb810a446
1/** @file
2  Graphics Output Protocol functions for the QEMU video controller.
3
4  Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
5
6  This program and the accompanying materials
7  are licensed and made available under the terms and conditions of the BSD License
8  which accompanies this distribution. The full text of the license may be found at
9  http://opensource.org/licenses/bsd-license.php
10
11  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14**/
15
16#include "Qemu.h"
17#include <IndustryStandard/Acpi.h>
18#include <Library/BltLib.h>
19
20STATIC
21VOID
22QemuVideoCompleteModeInfo (
23  IN  QEMU_VIDEO_MODE_DATA           *ModeData,
24  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info
25  )
26{
27  Info->Version = 0;
28  if (ModeData->ColorDepth == 8) {
29    Info->PixelFormat = PixelBitMask;
30    Info->PixelInformation.RedMask = PIXEL_RED_MASK;
31    Info->PixelInformation.GreenMask = PIXEL_GREEN_MASK;
32    Info->PixelInformation.BlueMask = PIXEL_BLUE_MASK;
33    Info->PixelInformation.ReservedMask = 0;
34  } else if (ModeData->ColorDepth == 24) {
35    Info->PixelFormat = PixelBitMask;
36    Info->PixelInformation.RedMask = PIXEL24_RED_MASK;
37    Info->PixelInformation.GreenMask = PIXEL24_GREEN_MASK;
38    Info->PixelInformation.BlueMask = PIXEL24_BLUE_MASK;
39    Info->PixelInformation.ReservedMask = 0;
40  } else if (ModeData->ColorDepth == 32) {
41    DEBUG ((EFI_D_INFO, "PixelBlueGreenRedReserved8BitPerColor\n"));
42    Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
43  }
44  Info->PixelsPerScanLine = Info->HorizontalResolution;
45}
46
47
48STATIC
49EFI_STATUS
50QemuVideoCompleteModeData (
51  IN  QEMU_VIDEO_PRIVATE_DATA           *Private,
52  OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode
53  )
54{
55  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info;
56  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     *FrameBufDesc;
57  QEMU_VIDEO_MODE_DATA           *ModeData;
58
59  ModeData = &Private->ModeData[Mode->Mode];
60  Info = Mode->Info;
61  QemuVideoCompleteModeInfo (ModeData, Info);
62
63  Private->PciIo->GetBarAttributes (
64                        Private->PciIo,
65                        0,
66                        NULL,
67                        (VOID**) &FrameBufDesc
68                        );
69
70  Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin;
71  Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution;
72  Mode->FrameBufferSize = Mode->FrameBufferSize * ((ModeData->ColorDepth + 7) / 8);
73  DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%x, FrameBufferSize: 0x%x\n", Mode->FrameBufferBase, Mode->FrameBufferSize));
74
75  FreePool (FrameBufDesc);
76  return EFI_SUCCESS;
77}
78
79
80//
81// Graphics Output Protocol Member Functions
82//
83EFI_STATUS
84EFIAPI
85QemuVideoGraphicsOutputQueryMode (
86  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
87  IN  UINT32                                ModeNumber,
88  OUT UINTN                                 *SizeOfInfo,
89  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
90  )
91/*++
92
93Routine Description:
94
95  Graphics Output protocol interface to query video mode
96
97  Arguments:
98    This                  - Protocol instance pointer.
99    ModeNumber            - The mode number to return information on.
100    Info                  - Caller allocated buffer that returns information about ModeNumber.
101    SizeOfInfo            - A pointer to the size, in bytes, of the Info buffer.
102
103  Returns:
104    EFI_SUCCESS           - Mode information returned.
105    EFI_BUFFER_TOO_SMALL  - The Info buffer was too small.
106    EFI_DEVICE_ERROR      - A hardware error occurred trying to retrieve the video mode.
107    EFI_NOT_STARTED       - Video display is not initialized. Call SetMode ()
108    EFI_INVALID_PARAMETER - One of the input args was NULL.
109
110--*/
111{
112  QEMU_VIDEO_PRIVATE_DATA  *Private;
113  QEMU_VIDEO_MODE_DATA     *ModeData;
114
115  Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
116
117  if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
118    return EFI_INVALID_PARAMETER;
119  }
120
121  *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
122  if (*Info == NULL) {
123    return EFI_OUT_OF_RESOURCES;
124  }
125
126  *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
127
128  ModeData = &Private->ModeData[ModeNumber];
129  (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
130  (*Info)->VerticalResolution   = ModeData->VerticalResolution;
131  QemuVideoCompleteModeInfo (ModeData, *Info);
132
133  return EFI_SUCCESS;
134}
135
136EFI_STATUS
137EFIAPI
138QemuVideoGraphicsOutputSetMode (
139  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
140  IN  UINT32                       ModeNumber
141  )
142/*++
143
144Routine Description:
145
146  Graphics Output protocol interface to set video mode
147
148  Arguments:
149    This             - Protocol instance pointer.
150    ModeNumber       - The mode number to be set.
151
152  Returns:
153    EFI_SUCCESS      - Graphics mode was changed.
154    EFI_DEVICE_ERROR - The device had an error and could not complete the request.
155    EFI_UNSUPPORTED  - ModeNumber is not supported by this device.
156
157--*/
158{
159  QEMU_VIDEO_PRIVATE_DATA    *Private;
160  QEMU_VIDEO_MODE_DATA       *ModeData;
161//  UINTN                             Count;
162
163  Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
164
165  if (ModeNumber >= This->Mode->MaxMode) {
166    return EFI_UNSUPPORTED;
167  }
168
169  ModeData = &Private->ModeData[ModeNumber];
170
171  if (Private->LineBuffer) {
172    gBS->FreePool (Private->LineBuffer);
173  }
174
175  Private->LineBuffer = AllocatePool (4 * ModeData->HorizontalResolution);
176  if (Private->LineBuffer == NULL) {
177    return EFI_OUT_OF_RESOURCES;
178  }
179
180  switch (Private->Variant) {
181  case QEMU_VIDEO_CIRRUS_5430:
182  case QEMU_VIDEO_CIRRUS_5446:
183    InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]);
184    break;
185  case QEMU_VIDEO_BOCHS_MMIO:
186  case QEMU_VIDEO_BOCHS:
187    InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]);
188    break;
189  default:
190    ASSERT (FALSE);
191    gBS->FreePool (Private->LineBuffer);
192    Private->LineBuffer = NULL;
193    return EFI_DEVICE_ERROR;
194  }
195
196  This->Mode->Mode = ModeNumber;
197  This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
198  This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
199  This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
200
201  QemuVideoCompleteModeData (Private, This->Mode);
202
203  BltLibConfigure (
204    (VOID*)(UINTN) This->Mode->FrameBufferBase,
205    This->Mode->Info
206    );
207
208  return EFI_SUCCESS;
209}
210
211EFI_STATUS
212EFIAPI
213QemuVideoGraphicsOutputBlt (
214  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
215  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer, OPTIONAL
216  IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION     BltOperation,
217  IN  UINTN                                 SourceX,
218  IN  UINTN                                 SourceY,
219  IN  UINTN                                 DestinationX,
220  IN  UINTN                                 DestinationY,
221  IN  UINTN                                 Width,
222  IN  UINTN                                 Height,
223  IN  UINTN                                 Delta
224  )
225/*++
226
227Routine Description:
228
229  Graphics Output protocol instance to block transfer for CirrusLogic device
230
231Arguments:
232
233  This          - Pointer to Graphics Output protocol instance
234  BltBuffer     - The data to transfer to screen
235  BltOperation  - The operation to perform
236  SourceX       - The X coordinate of the source for BltOperation
237  SourceY       - The Y coordinate of the source for BltOperation
238  DestinationX  - The X coordinate of the destination for BltOperation
239  DestinationY  - The Y coordinate of the destination for BltOperation
240  Width         - The width of a rectangle in the blt rectangle in pixels
241  Height        - The height of a rectangle in the blt rectangle in pixels
242  Delta         - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
243                  If a Delta of 0 is used, the entire BltBuffer will be operated on.
244                  If a subrectangle of the BltBuffer is used, then Delta represents
245                  the number of bytes in a row of the BltBuffer.
246
247Returns:
248
249  EFI_INVALID_PARAMETER - Invalid parameter passed in
250  EFI_SUCCESS - Blt operation success
251
252--*/
253{
254  EFI_STATUS                      Status;
255  EFI_TPL                         OriginalTPL;
256
257  //
258  // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
259  // We would not want a timer based event (Cursor, ...) to come in while we are
260  // doing this operation.
261  //
262  OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
263
264  switch (BltOperation) {
265  case EfiBltVideoToBltBuffer:
266  case EfiBltBufferToVideo:
267  case EfiBltVideoFill:
268  case EfiBltVideoToVideo:
269    Status = BltLibGopBlt (
270      BltBuffer,
271      BltOperation,
272      SourceX,
273      SourceY,
274      DestinationX,
275      DestinationY,
276      Width,
277      Height,
278      Delta
279      );
280    break;
281
282  default:
283    Status = EFI_INVALID_PARAMETER;
284    ASSERT (FALSE);
285  }
286
287  gBS->RestoreTPL (OriginalTPL);
288
289  return Status;
290}
291
292EFI_STATUS
293QemuVideoGraphicsOutputConstructor (
294  QEMU_VIDEO_PRIVATE_DATA  *Private
295  )
296{
297  EFI_STATUS                   Status;
298  EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
299
300
301  GraphicsOutput            = &Private->GraphicsOutput;
302  GraphicsOutput->QueryMode = QemuVideoGraphicsOutputQueryMode;
303  GraphicsOutput->SetMode   = QemuVideoGraphicsOutputSetMode;
304  GraphicsOutput->Blt       = QemuVideoGraphicsOutputBlt;
305
306  //
307  // Initialize the private data
308  //
309  Status = gBS->AllocatePool (
310                  EfiBootServicesData,
311                  sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
312                  (VOID **) &Private->GraphicsOutput.Mode
313                  );
314  if (EFI_ERROR (Status)) {
315    return Status;
316  }
317
318  Status = gBS->AllocatePool (
319                  EfiBootServicesData,
320                  sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
321                  (VOID **) &Private->GraphicsOutput.Mode->Info
322                  );
323  if (EFI_ERROR (Status)) {
324    goto FreeMode;
325  }
326  Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;
327  Private->GraphicsOutput.Mode->Mode    = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
328  Private->LineBuffer                   = NULL;
329
330  //
331  // Initialize the hardware
332  //
333  Status = GraphicsOutput->SetMode (GraphicsOutput, 0);
334  if (EFI_ERROR (Status)) {
335    goto FreeInfo;
336  }
337
338  DrawLogo (
339    Private,
340    Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,
341    Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution
342    );
343
344  return EFI_SUCCESS;
345
346FreeInfo:
347  FreePool (Private->GraphicsOutput.Mode->Info);
348
349FreeMode:
350  FreePool (Private->GraphicsOutput.Mode);
351  Private->GraphicsOutput.Mode = NULL;
352
353  return Status;
354}
355
356EFI_STATUS
357QemuVideoGraphicsOutputDestructor (
358  QEMU_VIDEO_PRIVATE_DATA  *Private
359  )
360/*++
361
362Routine Description:
363
364Arguments:
365
366Returns:
367
368  None
369
370--*/
371{
372  if (Private->LineBuffer != NULL) {
373    FreePool (Private->LineBuffer);
374  }
375
376  if (Private->GraphicsOutput.Mode != NULL) {
377    if (Private->GraphicsOutput.Mode->Info != NULL) {
378      gBS->FreePool (Private->GraphicsOutput.Mode->Info);
379    }
380    gBS->FreePool (Private->GraphicsOutput.Mode);
381  }
382
383  return EFI_SUCCESS;
384}
385
386
387