]> git.proxmox.com Git - mirror_edk2.git/blob - UnixPkg/UnixGopDxe/UnixGopScreen.c
Adding Simple Pointer, GOP, SimpleTextInEx, and Networking protocols to the emulator...
[mirror_edk2.git] / UnixPkg / UnixGopDxe / UnixGopScreen.c
1 /*++
2
3 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
4 Portions copyright (c) 2010, Apple, Inc. All rights reserved.
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 Module Name:
14
15 UnixGopScreen.c
16
17 Abstract:
18
19 This file produces the graphics abstration of UGA. It is called by
20 UnixGopDriver.c file which deals with the EFI 1.1 driver model.
21 This file just does graphics.
22
23 --*/
24
25 #include "UnixGop.h"
26
27 EFI_UNIX_THUNK_PROTOCOL *mUnix;
28 EFI_EVENT mGopScreenExitBootServicesEvent;
29
30 GOP_MODE_DATA mGopModeData[] = {
31 { 800, 600, 0, 0 },
32 { 640, 480, 0, 0 },
33 { 720, 400, 0, 0 },
34 {1024, 768, 0, 0 },
35 {1280, 1024, 0, 0 }
36 };
37
38
39 EFI_STATUS
40 UnixGopStartWindow (
41 IN GOP_PRIVATE_DATA *Private,
42 IN UINT32 HorizontalResolution,
43 IN UINT32 VerticalResolution,
44 IN UINT32 ColorDepth,
45 IN UINT32 RefreshRate
46 );
47
48 VOID
49 EFIAPI
50 KillUgaGopThread (
51 IN EFI_EVENT Event,
52 IN VOID *Context
53 );
54
55 //
56 // UGA Protocol Member Functions
57 //
58
59 EFI_STATUS
60 EFIAPI
61 UnixGopQuerytMode (
62 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
63 IN UINT32 ModeNumber,
64 OUT UINTN *SizeOfInfo,
65 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
66 )
67 {
68 GOP_PRIVATE_DATA *Private;
69
70 Private = GOP_PRIVATE_DATA_FROM_THIS (This);
71
72 if (Info == NULL || SizeOfInfo == NULL || (UINTN) ModeNumber >= This->Mode->MaxMode) {
73 return EFI_INVALID_PARAMETER;
74 }
75
76 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
77 if (*Info == NULL) {
78 return EFI_OUT_OF_RESOURCES;
79 }
80
81 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
82
83 (*Info)->Version = 0;
84 (*Info)->HorizontalResolution = Private->ModeData[ModeNumber].HorizontalResolution;
85 (*Info)->VerticalResolution = Private->ModeData[ModeNumber].VerticalResolution;
86 (*Info)->PixelFormat = PixelBltOnly;
87 (*Info)->PixelsPerScanLine = (*Info)->HorizontalResolution;
88
89 return EFI_SUCCESS;
90 }
91
92
93
94 EFI_STATUS
95 EFIAPI
96 UnixGopSetMode (
97 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
98 IN UINT32 ModeNumber
99 )
100 {
101 EFI_STATUS Status;
102 GOP_PRIVATE_DATA *Private;
103 GOP_MODE_DATA *ModeData;
104 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill;
105
106 Private = GOP_PRIVATE_DATA_FROM_THIS (This);
107
108 if (ModeNumber >= This->Mode->MaxMode) {
109 return EFI_UNSUPPORTED;
110 }
111
112 ModeData = &Private->ModeData[ModeNumber];
113 This->Mode->Mode = ModeNumber;
114 Private->GraphicsOutput.Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
115 Private->GraphicsOutput.Mode->Info->VerticalResolution = ModeData->VerticalResolution;
116 Private->GraphicsOutput.Mode->Info->PixelsPerScanLine = ModeData->HorizontalResolution;
117
118 if (Private->HardwareNeedsStarting) {
119 Status = UnixGopStartWindow (
120 Private,
121 ModeData->HorizontalResolution,
122 ModeData->VerticalResolution,
123 ModeData->ColorDepth,
124 ModeData->RefreshRate
125 );
126 if (EFI_ERROR (Status)) {
127 return EFI_DEVICE_ERROR;
128 }
129
130 Private->HardwareNeedsStarting = FALSE;
131 }
132
133
134 Status = Private->UgaIo->UgaSize(
135 Private->UgaIo,
136 ModeData->HorizontalResolution,
137 ModeData->VerticalResolution
138 );
139
140
141 Fill.Red = 0x7f;
142 Fill.Green = 0x7F;
143 Fill.Blue = 0x7f;
144 This->Blt (
145 This,
146 &Fill,
147 EfiBltVideoFill,
148 0,
149 0,
150 0,
151 0,
152 ModeData->HorizontalResolution,
153 ModeData->VerticalResolution,
154 ModeData->HorizontalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
155 );
156 return EFI_SUCCESS;
157 }
158
159
160
161 EFI_STATUS
162 EFIAPI
163 UnixGopBlt (
164 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
165 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
166 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
167 IN UINTN SourceX,
168 IN UINTN SourceY,
169 IN UINTN DestinationX,
170 IN UINTN DestinationY,
171 IN UINTN Width,
172 IN UINTN Height,
173 IN UINTN Delta OPTIONAL
174 )
175 {
176 GOP_PRIVATE_DATA *Private;
177 EFI_TPL OriginalTPL;
178 EFI_STATUS Status;
179 UGA_BLT_ARGS GopBltArgs;
180
181 Private = GOP_PRIVATE_DATA_FROM_THIS (This);
182
183 if ((BltOperation < 0) || (BltOperation >= EfiGraphicsOutputBltOperationMax)) {
184 return EFI_INVALID_PARAMETER;
185 }
186
187 if (Width == 0 || Height == 0) {
188 return EFI_INVALID_PARAMETER;
189 }
190 //
191 // If Delta is zero, then the entire BltBuffer is being used, so Delta
192 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
193 // the number of bytes in each row can be computed.
194 //
195 if (Delta == 0) {
196 Delta = Width * sizeof (EFI_UGA_PIXEL);
197 }
198
199 //
200 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
201 // We would not want a timer based event (Cursor, ...) to come in while we are
202 // doing this operation.
203 //
204 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
205
206 //
207 // Pack UGA Draw protocol parameters to UGA_BLT_ARGS structure to adapt to
208 // GopBlt() API of Unix UGA IO protocol.
209 //
210 GopBltArgs.DestinationX = DestinationX;
211 GopBltArgs.DestinationY = DestinationY;
212 GopBltArgs.Height = Height;
213 GopBltArgs.Width = Width;
214 GopBltArgs.SourceX = SourceX;
215 GopBltArgs.SourceY = SourceY;
216 GopBltArgs.Delta = Delta;
217 Status = Private->UgaIo->UgaBlt (
218 Private->UgaIo,
219 (EFI_UGA_PIXEL *)BltBuffer,
220 BltOperation,
221 &GopBltArgs
222 );
223
224 gBS->RestoreTPL (OriginalTPL);
225
226 return Status;
227 }
228
229
230 //
231 // Construction and Destruction functions
232 //
233
234 EFI_STATUS
235 UnixGopSupported (
236 IN EFI_UNIX_IO_PROTOCOL *UnixIo
237 )
238 /*++
239
240 Routine Description:
241
242 Arguments:
243
244 Returns:
245
246 None
247
248 --*/
249 // TODO: UnixIo - add argument and description to function comment
250 // TODO: EFI_UNSUPPORTED - add return value to function comment
251 // TODO: EFI_SUCCESS - add return value to function comment
252 {
253 //
254 // Check to see if the IO abstraction represents a device type we support.
255 //
256 // This would be replaced a check of PCI subsystem ID, etc.
257 //
258 if (!CompareGuid (UnixIo->TypeGuid, &gEfiUnixGopGuid)) {
259 return EFI_UNSUPPORTED;
260 }
261
262 return EFI_SUCCESS;
263 }
264
265
266 VOID
267 EFIAPI
268 GopPrivateInvokeRegisteredFunction (
269 IN VOID *Context,
270 IN EFI_KEY_DATA *KeyData
271 );
272
273
274 EFI_STATUS
275 UnixGopStartWindow (
276 IN GOP_PRIVATE_DATA *Private,
277 IN UINT32 HorizontalResolution,
278 IN UINT32 VerticalResolution,
279 IN UINT32 ColorDepth,
280 IN UINT32 RefreshRate
281 )
282 {
283 EFI_STATUS Status;
284
285 mUnix = Private->UnixThunk;
286
287 //
288 // Register to be notified on exit boot services so we can destroy the window.
289 //
290 Status = gBS->CreateEvent (
291 EVT_SIGNAL_EXIT_BOOT_SERVICES,
292 TPL_CALLBACK,
293 KillUgaGopThread,
294 Private,
295 &mGopScreenExitBootServicesEvent
296 );
297
298 Status = Private->UnixThunk->UgaCreate (&Private->UgaIo, Private->WindowName);
299 if (!EFI_ERROR (Status)) {
300 // Register callback to support RegisterKeyNotify()
301 Status = Private->UgaIo->UgaRegisterKeyNotify (Private->UgaIo, GopPrivateInvokeRegisteredFunction, Private);
302 ASSERT_EFI_ERROR (Status);
303 }
304 return Status;
305 }
306
307 EFI_STATUS
308 UnixGopConstructor (
309 GOP_PRIVATE_DATA *Private
310 )
311 {
312 Private->ModeData = mGopModeData;
313
314 Private->GraphicsOutput.QueryMode = UnixGopQuerytMode;
315 Private->GraphicsOutput.SetMode = UnixGopSetMode;
316 Private->GraphicsOutput.Blt = UnixGopBlt;
317
318 //
319 // Allocate buffer for Graphics Output Protocol mode information
320 //
321 Private->GraphicsOutput.Mode = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE));
322 if (Private->GraphicsOutput.Mode == NULL) {
323 return EFI_OUT_OF_RESOURCES;
324 }
325 Private->GraphicsOutput.Mode->Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
326 if (Private->GraphicsOutput.Mode->Info == NULL) {
327 return EFI_OUT_OF_RESOURCES;
328 }
329
330 Private->GraphicsOutput.Mode->MaxMode = sizeof(mGopModeData) / sizeof(GOP_MODE_DATA);
331 //
332 // Till now, we have no idea about the window size.
333 //
334 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
335 Private->GraphicsOutput.Mode->Info->Version = 0;
336 Private->GraphicsOutput.Mode->Info->HorizontalResolution = 0;
337 Private->GraphicsOutput.Mode->Info->VerticalResolution = 0;
338 Private->GraphicsOutput.Mode->Info->PixelFormat = PixelBltOnly;
339 Private->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
340 Private->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;
341 Private->GraphicsOutput.Mode->FrameBufferSize = 0;
342
343 Private->HardwareNeedsStarting = TRUE;
344 Private->UgaIo = NULL;
345
346 UnixGopInitializeSimpleTextInForWindow (Private);
347
348 UnixGopInitializeSimplePointerForWindow (Private);
349
350 return EFI_SUCCESS;
351 }
352
353
354
355 EFI_STATUS
356 UnixGopDestructor (
357 GOP_PRIVATE_DATA *Private
358 )
359 {
360 if (!Private->HardwareNeedsStarting) {
361 Private->UgaIo->UgaClose (Private->UgaIo);
362 Private->UgaIo = NULL;
363 }
364
365 //
366 // Free graphics output protocol occupied resource
367 //
368 if (Private->GraphicsOutput.Mode != NULL) {
369 if (Private->GraphicsOutput.Mode->Info != NULL) {
370 FreePool (Private->GraphicsOutput.Mode->Info);
371 }
372 FreePool (Private->GraphicsOutput.Mode);
373 }
374
375 return EFI_SUCCESS;
376 }
377
378 VOID
379 EFIAPI
380 KillUgaGopThread (
381 IN EFI_EVENT Event,
382 IN VOID *Context
383 )
384 /*++
385
386 Routine Description:
387
388 This is the UGA screen's callback notification function for exit-boot-services.
389 All we do here is call UnixGopDestructor().
390
391 Arguments:
392
393 Event - not used
394 Context - pointer to the Private structure.
395
396 Returns:
397
398 None.
399
400 --*/
401 {
402 EFI_STATUS Status;
403 Status = UnixGopDestructor (Context);
404 }