]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - UnixPkg/Sec/UgaX11.c
initialize variable before error returns.
[mirror_edk2.git] / UnixPkg / Sec / UgaX11.c
... / ...
CommitLineData
1/*++
2
3Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>
4Portions copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
5This program and the accompanying materials
6are licensed and made available under the terms and conditions of the BSD License
7which accompanies this distribution. The full text of the license may be found at
8http://opensource.org/licenses/bsd-license.php
9
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13--*/
14#include <Common/UnixInclude.h>
15
16#include <sys/ipc.h>
17#include <sys/shm.h>
18
19#include <PiPei.h>
20#include <Protocol/SimplePointer.h>
21#include <Protocol/SimpleTextIn.h>
22#include <Protocol/SimpleTextInEx.h>
23#include <Protocol/UgaDraw.h>
24#include <X11/Xlib.h>
25#include <X11/Xutil.h>
26#include <X11/Xos.h>
27#include <X11/extensions/XShm.h>
28#include <X11/keysym.h>
29#include <X11/cursorfont.h>
30
31#include <Protocol/UnixThunk.h>
32#include <Protocol/UnixUgaIo.h>
33
34#include <Ppi/StatusCode.h>
35
36#include <Library/PeCoffLib.h>
37#include <Library/BaseLib.h>
38#include <Library/BaseMemoryLib.h>
39#include <Library/PrintLib.h>
40#include <Library/PcdLib.h>
41#include <Library/DebugLib.h>
42
43#include "Gasket.h"
44#include "SecMain.h"
45
46
47extern void msSleep (unsigned long Milliseconds);
48
49/* XQueryPointer */
50
51struct uga_drv_shift_mask {
52 unsigned char shift;
53 unsigned char size;
54 unsigned char csize;
55};
56
57#define NBR_KEYS 32
58typedef struct {
59 EFI_UNIX_UGA_IO_PROTOCOL UgaIo;
60
61 Display *display;
62 int screen; /* values for window_size in main */
63 Window win;
64 GC gc;
65 Visual *visual;
66
67 int depth;
68 unsigned int width;
69 unsigned int height;
70 unsigned int line_bytes;
71 unsigned int pixel_shift;
72 unsigned char *image_data;
73
74 struct uga_drv_shift_mask r, g, b;
75
76 int use_shm;
77 XShmSegmentInfo xshm_info;
78 XImage *image;
79
80 unsigned int key_rd;
81 unsigned int key_wr;
82 unsigned int key_count;
83 EFI_KEY_DATA keys[NBR_KEYS];
84
85 EFI_KEY_STATE KeyState;
86
87 UGA_REGISTER_KEY_NOTIFY_CALLBACK RegisterdKeyCallback;
88 VOID *RegisterdKeyCallbackContext;
89
90 int previous_x;
91 int previous_y;
92 EFI_SIMPLE_POINTER_STATE pointer_state;
93 int pointer_state_changed;
94} UGA_IO_PRIVATE;
95
96void
97HandleEvents(UGA_IO_PRIVATE *drv);
98
99void
100fill_shift_mask (struct uga_drv_shift_mask *sm, unsigned long mask)
101{
102 sm->shift = 0;
103 sm->size = 0;
104 while ((mask & 1) == 0)
105 {
106 mask >>= 1;
107 sm->shift++;
108 }
109 while (mask & 1)
110 {
111 sm->size++;
112 mask >>= 1;
113 }
114 sm->csize = 8 - sm->size;
115}
116
117int
118TryCreateShmImage(UGA_IO_PRIVATE *drv)
119{
120 drv->image = XShmCreateImage (drv->display, drv->visual,
121 drv->depth, ZPixmap, NULL, &drv->xshm_info,
122 drv->width, drv->height);
123 if (drv->image == NULL)
124 return 0;
125
126 switch (drv->image->bitmap_unit) {
127 case 32:
128 drv->pixel_shift = 2;
129 break;
130 case 16:
131 drv->pixel_shift = 1;
132 break;
133 case 8:
134 drv->pixel_shift = 0;
135 break;
136 }
137
138 drv->xshm_info.shmid = shmget
139 (IPC_PRIVATE, drv->image->bytes_per_line * drv->image->height,
140 IPC_CREAT | 0777);
141 if (drv->xshm_info.shmid < 0) {
142 XDestroyImage(drv->image);
143 return 0;
144 }
145
146 drv->image_data = shmat (drv->xshm_info.shmid, NULL, 0);
147 if(!drv->image_data) {
148 shmctl (drv->xshm_info.shmid, IPC_RMID, NULL);
149 XDestroyImage(drv->image);
150 return 0;
151 }
152
153#ifndef __APPLE__
154 //
155 // This closes shared memory in real time on OS X. Only closes after folks quit using
156 // it on Linux.
157 //
158 /* Can this fail ? */
159 shmctl (drv->xshm_info.shmid, IPC_RMID, NULL);
160#endif
161
162 drv->xshm_info.shmaddr = (char*)drv->image_data;
163 drv->image->data = (char*)drv->image_data;
164
165 if (!XShmAttach (drv->display, &drv->xshm_info)) {
166 shmdt (drv->image_data);
167 XDestroyImage(drv->image);
168 return 0;
169 }
170 return 1;
171}
172
173EFI_STATUS
174UgaClose (EFI_UNIX_UGA_IO_PROTOCOL *UgaIo)
175{
176 UGA_IO_PRIVATE *drv = (UGA_IO_PRIVATE *)UgaIo;
177
178 if (drv == NULL)
179 return EFI_SUCCESS;
180 if (drv->image != NULL)
181 {
182 XDestroyImage(drv->image);
183
184 if (drv->use_shm)
185 shmdt (drv->image_data);
186
187 drv->image_data = NULL;
188 drv->image = NULL;
189 }
190 XDestroyWindow(drv->display, drv->win);
191 XCloseDisplay(drv->display);
192
193#ifdef __APPLE__
194 // Free up the shared memory
195 shmctl (drv->xshm_info.shmid, IPC_RMID, NULL);
196#endif
197
198 free(drv);
199 return EFI_SUCCESS;
200}
201
202EFI_STATUS
203UgaSize(EFI_UNIX_UGA_IO_PROTOCOL *UgaIo, UINT32 Width, UINT32 Height)
204{
205 UGA_IO_PRIVATE *drv = (UGA_IO_PRIVATE *)UgaIo;
206 XSizeHints size_hints;
207
208 /* Destroy current buffer if created. */
209 if (drv->image != NULL)
210 {
211 /* Before destroy buffer, need to make sure the buffer available for access. */
212 XDestroyImage(drv->image);
213
214 if (drv->use_shm)
215 shmdt (drv->image_data);
216
217 drv->image_data = NULL;
218 drv->image = NULL;
219 }
220
221 drv->width = Width;
222 drv->height = Height;
223 XResizeWindow (drv->display, drv->win, Width, Height);
224
225 /* Allocate image. */
226 if (XShmQueryExtension(drv->display) && TryCreateShmImage(drv)) {
227 drv->use_shm = 1;
228 } else {
229 drv->use_shm = 0;
230 if (drv->depth > 16)
231 drv->pixel_shift = 2;
232 else if (drv->depth > 8)
233 drv->pixel_shift = 1;
234 else
235 drv->pixel_shift = 0;
236
237 drv->image_data = malloc((drv->width * drv->height) << drv->pixel_shift);
238 drv->image = XCreateImage (drv->display, drv->visual, drv->depth,
239 ZPixmap, 0, (char *)drv->image_data,
240 drv->width, drv->height,
241 8 << drv->pixel_shift, 0);
242 }
243 drv->line_bytes = drv->image->bytes_per_line;
244 fill_shift_mask (&drv->r, drv->image->red_mask);
245 fill_shift_mask (&drv->g, drv->image->green_mask);
246 fill_shift_mask (&drv->b, drv->image->blue_mask);
247
248 /* Set WM hints. */
249 size_hints.flags = PSize | PMinSize | PMaxSize;
250 size_hints.min_width = size_hints.max_width = size_hints.base_width = Width;
251 size_hints.min_height = size_hints.max_height = size_hints.base_height = Height;
252 XSetWMNormalHints (drv->display, drv->win, &size_hints);
253
254 XMapWindow (drv->display, drv->win);
255 HandleEvents(drv);
256 return EFI_SUCCESS;
257}
258
259void
260handleKeyEvent(UGA_IO_PRIVATE *drv, XEvent *ev)
261{
262 KeySym keysym;
263 char str[4];
264 EFI_KEY_DATA KeyData;
265 int res;
266
267 if (drv->key_count == NBR_KEYS)
268 return;
269
270 res = XLookupString(&ev->xkey, str, sizeof(str), &keysym, NULL);
271 KeyData.Key.ScanCode = 0;
272 KeyData.Key.UnicodeChar = 0;
273 KeyData.KeyState.KeyShiftState = 0;
274
275 //
276 // KeyRelease is not supported (on Mac) so we can not easily implement Ex functions.
277 // If a modifier key is hit by its self we get a keysym. If a modfifier and key is hit
278 // we get the state bit set and keysym is the modified key.
279 //
280 // We use lack of state bits being set to clear ToggleState and KeyShiftState. We can
281 // also use the stat bits to set ToggleState and KeyShiftState.
282 // Skipping EFI_SCROLL_LOCK_ACTIVE & EFI_NUM_LOCK_ACTIVE since they are not on Macs
283 //
284 if ((ev->xkey.state & LockMask) == 0) {
285 drv->KeyState.KeyToggleState &= ~EFI_CAPS_LOCK_ACTIVE;
286 } else {
287 drv->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
288 }
289
290 if ((ev->xkey.state & ControlMask) == 0) {
291 drv->KeyState.KeyShiftState &= ~(EFI_RIGHT_CONTROL_PRESSED | EFI_LEFT_CONTROL_PRESSED);
292 } else if ((drv->KeyState.KeyShiftState & EFI_RIGHT_CONTROL_PRESSED) == 0) {
293 drv->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;
294 }
295
296 if ((ev->xkey.state & ShiftMask) == 0) {
297 drv->KeyState.KeyShiftState &= ~(EFI_RIGHT_SHIFT_PRESSED | EFI_LEFT_SHIFT_PRESSED);
298 } else if ((drv->KeyState.KeyShiftState & EFI_RIGHT_SHIFT_PRESSED) == 0) {
299 drv->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;
300 }
301
302 if ((ev->xkey.state & Mod2Mask) == 0) {
303 drv->KeyState.KeyShiftState &= ~(EFI_RIGHT_LOGO_PRESSED | EFI_LEFT_LOGO_PRESSED);
304 } else if ((drv->KeyState.KeyShiftState & EFI_RIGHT_LOGO_PRESSED) == 0) {
305 drv->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;
306 }
307
308 if ((ev->xkey.state & 0x2000) == 0) {
309 drv->KeyState.KeyShiftState &= ~(EFI_LEFT_ALT_PRESSED);
310 } else {
311 drv->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED;
312 }
313
314
315 switch (keysym) {
316 case XK_Control_R:
317 drv->KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;
318 break;
319 case XK_Control_L:
320 drv->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;
321 break;
322
323 case XK_Shift_R:
324 drv->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;
325 break;
326 case XK_Shift_L:
327 drv->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;
328 break;
329
330 case XK_Mode_switch:
331 drv->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED;
332 break;
333
334 case XK_Meta_R:
335 drv->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;
336 break;
337 case XK_Meta_L:
338 drv->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;
339 break;
340
341 case XK_Home: KeyData.Key.ScanCode = SCAN_HOME; break;
342 case XK_End: KeyData.Key.ScanCode = SCAN_END; break;
343 case XK_Left: KeyData.Key.ScanCode = SCAN_LEFT; break;
344 case XK_Right: KeyData.Key.ScanCode = SCAN_RIGHT; break;
345 case XK_Up: KeyData.Key.ScanCode = SCAN_UP; break;
346 case XK_Down: KeyData.Key.ScanCode = SCAN_DOWN; break;
347 case XK_Delete: KeyData.Key.ScanCode = SCAN_DELETE; break;
348 case XK_Insert: KeyData.Key.ScanCode = SCAN_INSERT; break;
349 case XK_Page_Up: KeyData.Key.ScanCode = SCAN_PAGE_UP; break;
350 case XK_Page_Down: KeyData.Key.ScanCode = SCAN_PAGE_DOWN; break;
351 case XK_Escape: KeyData.Key.ScanCode = SCAN_ESC; break;
352
353 case XK_F1: KeyData.Key.ScanCode = SCAN_F1; break;
354 case XK_F2: KeyData.Key.ScanCode = SCAN_F2; break;
355 case XK_F3: KeyData.Key.ScanCode = SCAN_F3; break;
356 case XK_F4: KeyData.Key.ScanCode = SCAN_F4; break;
357 case XK_F5: KeyData.Key.ScanCode = SCAN_F5; break;
358 case XK_F6: KeyData.Key.ScanCode = SCAN_F6; break;
359 case XK_F7: KeyData.Key.ScanCode = SCAN_F7; break;
360 case XK_F8: KeyData.Key.ScanCode = SCAN_F8; break;
361 case XK_F9: KeyData.Key.ScanCode = SCAN_F9; break;
362
363 default:
364 if (res == 1) {
365 KeyData.Key.UnicodeChar = str[0];
366 } else {
367 return;
368 }
369 }
370
371 // The global state is our state
372 KeyData.KeyState.KeyShiftState = drv->KeyState.KeyShiftState;
373 KeyData.KeyState.KeyToggleState = drv->KeyState.KeyToggleState;
374
375 CopyMem (&drv->keys[drv->key_wr], &KeyData, sizeof (EFI_KEY_DATA));
376 drv->key_wr = (drv->key_wr + 1) % NBR_KEYS;
377 drv->key_count++;
378
379
380#if defined(__APPLE__) || defined(MDE_CPU_X64)
381 ReverseGasketUint64Uint64 (drv->RegisterdKeyCallback ,drv->RegisterdKeyCallbackContext, &KeyData);
382#else
383 drv->RegisterdKeyCallback (drv->RegisterdKeyCallbackContext, &KeyData);
384#endif
385
386
387}
388
389
390void
391handleMouseMoved(UGA_IO_PRIVATE *drv, XEvent *ev)
392{
393 if ( ev->xmotion.x != drv->previous_x )
394 {
395 drv->pointer_state.RelativeMovementX += ( ev->xmotion.x - drv->previous_x );
396 drv->previous_x = ev->xmotion.x;
397 drv->pointer_state_changed = 1;
398 }
399
400 if ( ev->xmotion.y != drv->previous_y )
401 {
402 drv->pointer_state.RelativeMovementY += ( ev->xmotion.y - drv->previous_y );
403 drv->previous_y = ev->xmotion.y;
404 drv->pointer_state_changed = 1;
405 }
406
407 drv->pointer_state.RelativeMovementZ = 0;
408}
409
410void
411handleMouseDown(UGA_IO_PRIVATE *drv, XEvent *ev, BOOLEAN Pressed)
412{
413 if ( ev->xbutton.button == Button1 )
414 {
415 drv->pointer_state_changed = ( drv->pointer_state.LeftButton != Pressed );
416 drv->pointer_state.LeftButton = Pressed;
417 }
418 if ( ev->xbutton.button == Button2 )
419 {
420 drv->pointer_state_changed = ( drv->pointer_state.RightButton != Pressed );
421 drv->pointer_state.RightButton = Pressed;
422 }
423}
424
425void
426Redraw(UGA_IO_PRIVATE *drv, UINTN X, UINTN Y, UINTN Width, UINTN Height)
427{
428 if (drv->use_shm)
429 XShmPutImage (drv->display, drv->win, drv->gc, drv->image,
430 X, Y, X, Y, Width, Height, False);
431 else
432 XPutImage (drv->display, drv->win, drv->gc, drv->image,
433 X, Y, X, Y, Width, Height);
434 XFlush(drv->display);
435}
436
437void
438HandleEvent(UGA_IO_PRIVATE *drv, XEvent *ev)
439{
440 switch (ev->type)
441 {
442 case Expose:
443 Redraw(drv, ev->xexpose.x, ev->xexpose.y,
444 ev->xexpose.width, ev->xexpose.height);
445 break;
446 case GraphicsExpose:
447 Redraw(drv, ev->xgraphicsexpose.x, ev->xgraphicsexpose.y,
448 ev->xgraphicsexpose.width, ev->xgraphicsexpose.height);
449 break;
450 case KeyPress:
451 handleKeyEvent(drv, ev);
452 break;
453 case KeyRelease:
454 break;
455 case MappingNotify:
456 XRefreshKeyboardMapping(&ev->xmapping);
457 break;
458 case MotionNotify:
459 handleMouseMoved(drv, ev);
460 break;
461 case ButtonPress:
462 handleMouseDown(drv, ev, TRUE);
463 break;
464 case ButtonRelease:
465 handleMouseDown(drv, ev, FALSE);
466 break;
467#if 0
468 case DestroyNotify:
469 XCloseDisplay (drv->display);
470 exit (1);
471 break;
472#endif
473 case NoExpose:
474 default:
475 break;
476 }
477}
478
479void
480HandleEvents(UGA_IO_PRIVATE *drv)
481{
482 while (XPending(drv->display) != 0)
483 {
484 XEvent ev;
485
486 XNextEvent (drv->display, &ev);
487 HandleEvent(drv, &ev);
488 }
489}
490
491unsigned long
492UgaPixelToColor (UGA_IO_PRIVATE *drv, EFI_UGA_PIXEL pixel)
493{
494 return ((pixel.Red >> drv->r.csize) << drv->r.shift)
495 | ((pixel.Green >> drv->g.csize) << drv->g.shift)
496 | ((pixel.Blue >> drv->b.csize) << drv->b.shift);
497}
498
499EFI_UGA_PIXEL
500UgaColorToPixel (UGA_IO_PRIVATE *drv, unsigned long val)
501{
502 EFI_UGA_PIXEL res;
503
504 memset (&res, 0, sizeof (EFI_UGA_PIXEL));
505 /* FIXME: should round instead of truncate. */
506 res.Red = (val >> drv->r.shift) << drv->r.csize;
507 res.Green = (val >> drv->g.shift) << drv->g.csize;
508 res.Blue = (val >> drv->b.shift) << drv->b.csize;
509
510 return res;
511}
512
513STATIC EFI_STATUS
514CheckKeyInternal( UGA_IO_PRIVATE *drv, BOOLEAN delay )
515{
516 HandleEvents(drv);
517 if (drv->key_count != 0)
518 return EFI_SUCCESS;
519 if ( delay )
520 /* EFI is polling. Be CPU-friendly. */
521 msSleep (20);
522 return EFI_NOT_READY;
523 }
524
525EFI_STATUS
526UgaCheckKey(EFI_UNIX_UGA_IO_PROTOCOL *UgaIo)
527{
528 UGA_IO_PRIVATE *drv = (UGA_IO_PRIVATE *)UgaIo;
529 return( CheckKeyInternal( drv, TRUE ) );
530}
531
532EFI_STATUS
533EFIAPI
534UgaGetKey (
535 IN EFI_UNIX_UGA_IO_PROTOCOL *UgaIo,
536 IN EFI_KEY_DATA *KeyData
537 )
538{
539 UGA_IO_PRIVATE *drv = (UGA_IO_PRIVATE *)UgaIo;
540 EFI_STATUS status;
541
542 status = CheckKeyInternal(drv, FALSE);
543 if (status != EFI_SUCCESS)
544 return status;
545
546 CopyMem (KeyData, &drv->keys[drv->key_rd], sizeof (EFI_KEY_DATA));
547 drv->key_rd = (drv->key_rd + 1) % NBR_KEYS;
548 drv->key_count--;
549 return EFI_SUCCESS;
550}
551
552
553EFI_STATUS
554EFIAPI
555UgaKeySetState (
556 IN EFI_UNIX_UGA_IO_PROTOCOL *UgaIo,
557 IN EFI_KEY_TOGGLE_STATE *KeyToggleState
558 )
559{
560 UGA_IO_PRIVATE *drv = (UGA_IO_PRIVATE *)UgaIo;
561// XKeyEvent event;
562
563 if (*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) {
564 if ((drv->KeyState.KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == 0) {
565 //
566 // We could create an XKeyEvent and send a XK_Caps_Lock to
567 // the UGA/GOP Window
568 //
569 }
570 }
571
572 drv->KeyState.KeyToggleState = *KeyToggleState;
573 return EFI_SUCCESS;
574}
575
576
577EFI_STATUS
578EFIAPI
579UgaRegisterKeyNotify (
580 IN EFI_UNIX_UGA_IO_PROTOCOL *UgaIo,
581 IN UGA_REGISTER_KEY_NOTIFY_CALLBACK CallBack,
582 IN VOID *Context
583 )
584{
585 UGA_IO_PRIVATE *drv = (UGA_IO_PRIVATE *)UgaIo;
586
587 drv->RegisterdKeyCallback = CallBack;
588 drv->RegisterdKeyCallbackContext = Context;
589
590 return EFI_SUCCESS;
591}
592
593
594EFI_STATUS
595UgaBlt(
596 IN EFI_UNIX_UGA_IO_PROTOCOL *UgaIo,
597 IN EFI_UGA_PIXEL *BltBuffer OPTIONAL,
598 IN EFI_UGA_BLT_OPERATION BltOperation,
599 IN UGA_BLT_ARGS *Args
600 )
601{
602 UGA_IO_PRIVATE *Private = (UGA_IO_PRIVATE *)UgaIo;
603 UINTN DstY;
604 UINTN SrcY;
605 UINTN DstX;
606 UINTN SrcX;
607 UINTN Index;
608 EFI_UGA_PIXEL *Blt;
609 UINT8 *Dst;
610 UINT8 *Src;
611 UINTN Nbr;
612 unsigned long Color;
613
614 //
615 // Check bounds
616 //
617 if (BltOperation == EfiUgaVideoToBltBuffer
618 || BltOperation == EfiUgaVideoToVideo) {
619 //
620 // Source is Video.
621 //
622 if (Args->SourceY + Args->Height > Private->height) {
623 return EFI_INVALID_PARAMETER;
624 }
625
626 if (Args->SourceX + Args->Width > Private->width) {
627 return EFI_INVALID_PARAMETER;
628 }
629 }
630
631 if (BltOperation == EfiUgaBltBufferToVideo
632 || BltOperation == EfiUgaVideoToVideo
633 || BltOperation == EfiUgaVideoFill) {
634 //
635 // Destination is Video
636 //
637 if (Args->DestinationY + Args->Height > Private->height) {
638 return EFI_INVALID_PARAMETER;
639 }
640
641 if (Args->DestinationX + Args->Width > Private->width) {
642 return EFI_INVALID_PARAMETER;
643 }
644 }
645
646 switch (BltOperation) {
647 case EfiUgaVideoToBltBuffer:
648 Blt = (EFI_UGA_PIXEL *)((UINT8 *)BltBuffer + (Args->DestinationY * Args->Delta) + Args->DestinationX * sizeof (EFI_UGA_PIXEL));
649 Args->Delta -= Args->Width * sizeof (EFI_UGA_PIXEL);
650 for (SrcY = Args->SourceY; SrcY < (Args->Height + Args->SourceY); SrcY++) {
651 for (SrcX = Args->SourceX; SrcX < (Args->Width + Args->SourceX); SrcX++) {
652 *Blt++ = UgaColorToPixel(Private,
653 XGetPixel(Private->image, SrcX, SrcY));
654 }
655 Blt = (EFI_UGA_PIXEL *) ((UINT8 *) Blt + Args->Delta);
656 }
657 break;
658 case EfiUgaBltBufferToVideo:
659 Blt = (EFI_UGA_PIXEL *)((UINT8 *)BltBuffer + (Args->SourceY * Args->Delta) + Args->SourceX * sizeof (EFI_UGA_PIXEL));
660 Args->Delta -= Args->Width * sizeof (EFI_UGA_PIXEL);
661 for (DstY = Args->DestinationY; DstY < (Args->Height + Args->DestinationY); DstY++) {
662 for (DstX = Args->DestinationX; DstX < (Args->Width + Args->DestinationX); DstX++) {
663 XPutPixel(Private->image, DstX, DstY, UgaPixelToColor(Private, *Blt));
664 Blt++;
665 }
666 Blt = (EFI_UGA_PIXEL *) ((UINT8 *) Blt + Args->Delta);
667 }
668 break;
669 case EfiUgaVideoToVideo:
670 Dst = Private->image_data + (Args->DestinationX << Private->pixel_shift)
671 + Args->DestinationY * Private->line_bytes;
672 Src = Private->image_data + (Args->SourceX << Private->pixel_shift)
673 + Args->SourceY * Private->line_bytes;
674 Nbr = Args->Width << Private->pixel_shift;
675 if (Args->DestinationY < Args->SourceY) {
676 for (Index = 0; Index < Args->Height; Index++) {
677 memcpy (Dst, Src, Nbr);
678 Dst += Private->line_bytes;
679 Src += Private->line_bytes;
680 }
681 }
682 else {
683 Dst += (Args->Height - 1) * Private->line_bytes;
684 Src += (Args->Height - 1) * Private->line_bytes;
685 for (Index = 0; Index < Args->Height; Index++) {
686 //
687 // Source and Destination Y may be equal, therefore Dst and Src may
688 // overlap.
689 //
690 memmove (Dst, Src, Nbr);
691 Dst -= Private->line_bytes;
692 Src -= Private->line_bytes;
693 }
694 }
695 break;
696 case EfiUgaVideoFill:
697 Color = UgaPixelToColor(Private, *BltBuffer);
698 for (DstY = Args->DestinationY; DstY < (Args->Height + Args->DestinationY); DstY++) {
699 for (DstX = Args->DestinationX; DstX < (Args->Width + Args->DestinationX); DstX++) {
700 XPutPixel(Private->image, DstX, DstY, Color);
701 }
702 }
703 break;
704 default:
705 return EFI_INVALID_PARAMETER;
706 }
707
708 //
709 // Refresh screen.
710 //
711 switch (BltOperation) {
712 case EfiUgaVideoToVideo:
713 XCopyArea(Private->display, Private->win, Private->win, Private->gc,
714 Args->SourceX, Args->SourceY, Args->Width, Args->Height, Args->DestinationX, Args->DestinationY);
715 while (1) {
716 XEvent ev;
717
718 XNextEvent (Private->display, &ev);
719 HandleEvent(Private, &ev);
720 if (ev.type == NoExpose || ev.type == GraphicsExpose)
721 break;
722 }
723 break;
724 case EfiUgaVideoFill:
725 Color = UgaPixelToColor(Private, *BltBuffer);
726 XSetForeground(Private->display, Private->gc, Color);
727 XFillRectangle(Private->display, Private->win, Private->gc,
728 Args->DestinationX, Args->DestinationY, Args->Width, Args->Height);
729 XFlush(Private->display);
730 break;
731 case EfiUgaBltBufferToVideo:
732 Redraw(Private, Args->DestinationX, Args->DestinationY, Args->Width, Args->Height);
733 break;
734 default:
735 break;
736 }
737 return EFI_SUCCESS;
738}
739
740STATIC EFI_STATUS
741CheckPointerInternal( UGA_IO_PRIVATE *drv, BOOLEAN delay )
742{
743 HandleEvents(drv);
744 if (drv->pointer_state_changed != 0)
745 return EFI_SUCCESS;
746 if ( delay )
747 /* EFI is polling. Be CPU-friendly. */
748 msSleep (20);
749 return EFI_NOT_READY;
750}
751
752EFI_STATUS
753UgaCheckPointer(EFI_UNIX_UGA_IO_PROTOCOL *UgaIo)
754{
755 UGA_IO_PRIVATE *drv = (UGA_IO_PRIVATE *)UgaIo;
756 return( CheckPointerInternal( drv, TRUE ) );
757}
758
759EFI_STATUS
760UgaGetPointerState (EFI_UNIX_UGA_IO_PROTOCOL *UgaIo, EFI_SIMPLE_POINTER_STATE *state)
761{
762 UGA_IO_PRIVATE *drv = (UGA_IO_PRIVATE *)UgaIo;
763 EFI_STATUS status;
764
765 status = CheckPointerInternal( drv, FALSE );
766 if (status != EFI_SUCCESS)
767 return status;
768
769 memcpy( state, &drv->pointer_state, sizeof( EFI_SIMPLE_POINTER_STATE ) );
770
771 drv->pointer_state.RelativeMovementX = 0;
772 drv->pointer_state.RelativeMovementY = 0;
773 drv->pointer_state.RelativeMovementZ = 0;
774 drv->pointer_state_changed = 0;
775 return EFI_SUCCESS;
776}
777
778EFI_STATUS
779UgaCreate (EFI_UNIX_UGA_IO_PROTOCOL **Uga, CONST CHAR16 *Title)
780{
781 UGA_IO_PRIVATE *drv;
782 unsigned int border_width = 0;
783 char *display_name = NULL;
784 int title_len;
785
786 drv = (UGA_IO_PRIVATE *)calloc (1, sizeof (UGA_IO_PRIVATE));
787 if (drv == NULL)
788 return EFI_OUT_OF_RESOURCES;
789
790#if defined(__APPLE__) || defined(MDE_CPU_X64)
791//
792//
793//
794 drv->UgaIo.UgaClose = GasketUgaClose;
795 drv->UgaIo.UgaSize = GasketUgaSize;
796 drv->UgaIo.UgaCheckKey = GasketUgaCheckKey;
797 drv->UgaIo.UgaGetKey = GasketUgaGetKey;
798 drv->UgaIo.UgaKeySetState = GasketUgaKeySetState;
799 drv->UgaIo.UgaRegisterKeyNotify = GasketUgaRegisterKeyNotify;
800 drv->UgaIo.UgaBlt = GasketUgaBlt;
801 drv->UgaIo.UgaCheckPointer = GasketUgaCheckPointer;
802 drv->UgaIo.UgaGetPointerState = GasketUgaGetPointerState;
803#else
804 drv->UgaIo.UgaClose = UgaClose;
805 drv->UgaIo.UgaSize = UgaSize;
806 drv->UgaIo.UgaCheckKey = UgaCheckKey;
807 drv->UgaIo.UgaGetKey = UgaGetKey;
808 drv->UgaIo.UgaKeySetState = UgaKeySetState;
809 drv->UgaIo.UgaRegisterKeyNotify = UgaRegisterKeyNotify;
810 drv->UgaIo.UgaBlt = UgaBlt;
811 drv->UgaIo.UgaCheckPointer = UgaCheckPointer;
812 drv->UgaIo.UgaGetPointerState = UgaGetPointerState;
813#endif
814
815
816
817 drv->key_count = 0;
818 drv->key_rd = 0;
819 drv->key_wr = 0;
820 drv->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
821 drv->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
822 drv->RegisterdKeyCallback = NULL;
823 drv->RegisterdKeyCallbackContext = NULL;
824
825
826 drv->display = XOpenDisplay (display_name);
827 if (drv->display == NULL)
828 {
829 fprintf (stderr, "uga: cannot connect to X server %s\n",
830 XDisplayName (display_name));
831 free (drv);
832 return EFI_DEVICE_ERROR;
833 }
834 drv->screen = DefaultScreen (drv->display);
835 drv->visual = DefaultVisual (drv->display, drv->screen);
836 drv->win = XCreateSimpleWindow
837 (drv->display, RootWindow (drv->display, drv->screen),
838 0, 0, 4, 4, border_width,
839 WhitePixel (drv->display, drv->screen),
840 BlackPixel (drv->display, drv->screen));
841
842 drv->depth = DefaultDepth (drv->display, drv->screen);
843 XDefineCursor (drv->display, drv->win, XCreateFontCursor (drv->display, XC_pirate));
844
845 /* Compute title len and convert to Ascii. */
846 for (title_len = 0; Title[title_len] != 0; title_len++)
847 ;
848 {
849 char title[title_len + 1];
850 int i;
851 for (i = 0; i < title_len; i++)
852 title[i] = Title[i];
853 title[i] = 0;
854
855 XStoreName (drv->display, drv->win, title);
856 }
857
858 XSelectInput (drv->display, drv->win,
859 ExposureMask | KeyPressMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask );
860 drv->gc = DefaultGC (drv->display, drv->screen);
861
862 *Uga = (EFI_UNIX_UGA_IO_PROTOCOL *)drv;
863 return EFI_SUCCESS;
864}