3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 This file produces the graphics abstration of GOP. It is called by
19 WinNtGopDriver.c file which deals with the UEFI 2.0 driver model.
20 This file just does graphics.
27 EFI_WIN_NT_THUNK_PROTOCOL
*mWinNt
;
28 DWORD mTlsIndex
= TLS_OUT_OF_INDEXES
;
29 DWORD mTlsIndexUseCount
= 0; // lets us know when we can free mTlsIndex.
30 static EFI_EVENT mGopScreenExitBootServicesEvent
;
31 GOP_MODE_DATA mGopModeData
[] = {
41 IN GOP_PRIVATE_DATA
*Private
,
42 IN UINT32 HorizontalResolution
,
43 IN UINT32 VerticalResolution
,
58 WinNtGopConvertParamToEfiKeyShiftState (
59 IN GOP_PRIVATE_DATA
*Private
,
66 // BUGBUG: Only GetAsyncKeyState() and GetKeyState() can distinguish
67 // left and right Ctrl, and Shift key.
68 // Neither of the two is defined in EFI_WIN_NT_THUNK_PROTOCOL.
69 // Therefor, we can not set the correct Shift state here.
72 Private
->LeftShift
= Flag
;
75 Private
->LeftCtrl
= Flag
;
78 Private
->LeftLogo
= Flag
;
81 Private
->RightLogo
= Flag
;
87 // BUGBUG: PrintScreen/SysRq can not trigger WM_KEYDOWN message,
88 // so SySReq shift state is not supported here.
91 Private
->SysReq
= Flag
;
98 WinNtGopConvertParamToEfiKey (
99 IN GOP_PRIVATE_DATA
*Private
,
101 IN EFI_INPUT_KEY
*Key
105 case VK_HOME
: Key
->ScanCode
= SCAN_HOME
; break;
106 case VK_END
: Key
->ScanCode
= SCAN_END
; break;
107 case VK_LEFT
: Key
->ScanCode
= SCAN_LEFT
; break;
108 case VK_RIGHT
: Key
->ScanCode
= SCAN_RIGHT
; break;
109 case VK_UP
: Key
->ScanCode
= SCAN_UP
; break;
110 case VK_DOWN
: Key
->ScanCode
= SCAN_DOWN
; break;
111 case VK_DELETE
: Key
->ScanCode
= SCAN_DELETE
; break;
112 case VK_INSERT
: Key
->ScanCode
= SCAN_INSERT
; break;
113 case VK_PRIOR
: Key
->ScanCode
= SCAN_PAGE_UP
; break;
114 case VK_NEXT
: Key
->ScanCode
= SCAN_PAGE_DOWN
; break;
115 case VK_ESCAPE
: Key
->ScanCode
= SCAN_ESC
; break;
117 case VK_F1
: Key
->ScanCode
= SCAN_F1
; break;
118 case VK_F2
: Key
->ScanCode
= SCAN_F2
; break;
119 case VK_F3
: Key
->ScanCode
= SCAN_F3
; break;
120 case VK_F4
: Key
->ScanCode
= SCAN_F4
; break;
121 case VK_F5
: Key
->ScanCode
= SCAN_F5
; break;
122 case VK_F6
: Key
->ScanCode
= SCAN_F6
; break;
123 case VK_F7
: Key
->ScanCode
= SCAN_F7
; break;
124 case VK_F8
: Key
->ScanCode
= SCAN_F8
; break;
125 case VK_F9
: Key
->ScanCode
= SCAN_F9
; break;
126 case VK_F11
: Key
->ScanCode
= SCAN_F11
; break;
127 case VK_F12
: Key
->ScanCode
= SCAN_F12
; break;
129 case VK_F13
: Key
->ScanCode
= SCAN_F13
; break;
130 case VK_F14
: Key
->ScanCode
= SCAN_F14
; break;
131 case VK_F15
: Key
->ScanCode
= SCAN_F15
; break;
132 case VK_F16
: Key
->ScanCode
= SCAN_F16
; break;
133 case VK_F17
: Key
->ScanCode
= SCAN_F17
; break;
134 case VK_F18
: Key
->ScanCode
= SCAN_F18
; break;
135 case VK_F19
: Key
->ScanCode
= SCAN_F19
; break;
136 case VK_F20
: Key
->ScanCode
= SCAN_F20
; break;
137 case VK_F21
: Key
->ScanCode
= SCAN_F21
; break;
138 case VK_F22
: Key
->ScanCode
= SCAN_F22
; break;
139 case VK_F23
: Key
->ScanCode
= SCAN_F23
; break;
140 case VK_F24
: Key
->ScanCode
= SCAN_F24
; break;
146 Private
->NumLock
= !Private
->NumLock
;
149 Private
->ScrollLock
= !Private
->ScrollLock
;
152 Private
->CapsLock
= !Private
->CapsLock
;
156 WinNtGopConvertParamToEfiKeyShiftState (Private
, wParam
, TRUE
);
161 // GOP Protocol Member Functions
166 Graphics Output protocol interface to get video mode
168 @param This Protocol instance pointer.
169 @param ModeNumber The mode number to return information on.
170 @param Info Caller allocated buffer that returns information
172 @param SizeOfInfo A pointer to the size, in bytes, of the Info
175 @retval EFI_SUCCESS Mode information returned.
176 @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.
177 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
179 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
180 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
186 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
187 IN UINT32 ModeNumber
,
188 OUT UINTN
*SizeOfInfo
,
189 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
192 GOP_PRIVATE_DATA
*Private
;
194 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
196 if (Info
== NULL
|| SizeOfInfo
== NULL
|| (UINTN
) ModeNumber
>= This
->Mode
->MaxMode
) {
197 return EFI_INVALID_PARAMETER
;
200 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
202 return EFI_OUT_OF_RESOURCES
;
205 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
207 (*Info
)->Version
= 0;
208 (*Info
)->HorizontalResolution
= Private
->ModeData
[ModeNumber
].HorizontalResolution
;
209 (*Info
)->VerticalResolution
= Private
->ModeData
[ModeNumber
].VerticalResolution
;
210 (*Info
)->PixelFormat
= PixelBltOnly
;
211 (*Info
)->PixelsPerScanLine
= (*Info
)->HorizontalResolution
;
218 Graphics Output protocol interface to set video mode
220 @param This Protocol instance pointer.
221 @param ModeNumber The mode number to be set.
223 @retval EFI_SUCCESS Graphics mode was changed.
224 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
226 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
232 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
237 GOP_PRIVATE_DATA
*Private
;
238 GOP_MODE_DATA
*ModeData
;
239 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill
;
240 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*NewFillLine
;
246 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
248 if (ModeNumber
>= This
->Mode
->MaxMode
) {
249 return EFI_UNSUPPORTED
;
252 if (ModeNumber
== This
->Mode
->Mode
) {
256 ModeData
= &Private
->ModeData
[ModeNumber
];
257 This
->Mode
->Mode
= ModeNumber
;
258 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
259 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
260 Private
->GraphicsOutput
.Mode
->Info
->PixelsPerScanLine
= ModeData
->HorizontalResolution
;
262 if (Private
->HardwareNeedsStarting
) {
263 Status
= WinNtGopStartWindow (
265 ModeData
->HorizontalResolution
,
266 ModeData
->VerticalResolution
,
267 ModeData
->ColorDepth
,
268 ModeData
->RefreshRate
270 if (EFI_ERROR (Status
)) {
271 return EFI_DEVICE_ERROR
;
274 Private
->HardwareNeedsStarting
= FALSE
;
277 // Change the resolution and resize of the window
281 // Free the old buffer. We do not save the content of the old buffer since the
282 // screen is to be cleared anyway. Clearing the screen is required by the EFI spec.
283 // See UEFI spec -EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode()
285 Private
->WinNtThunk
->HeapFree (Private
->WinNtThunk
->GetProcessHeap (), 0, Private
->VirtualScreenInfo
);
288 // Allocate DIB frame buffer directly from NT for performance enhancement
289 // This buffer is the virtual screen/frame buffer. This buffer is not the
290 // same a a frame buffer. The first row of this buffer will be the bottom
291 // line of the image. This is an artifact of the way we draw to the screen.
293 Size
= ModeData
->HorizontalResolution
* ModeData
->VerticalResolution
* sizeof (RGBQUAD
) + sizeof (BITMAPV4HEADER
);
294 Private
->VirtualScreenInfo
= Private
->WinNtThunk
->HeapAlloc (
295 Private
->WinNtThunk
->GetProcessHeap (),
301 // Update the virtual screen info data structure
303 Private
->VirtualScreenInfo
->bV4Size
= sizeof (BITMAPV4HEADER
);
304 Private
->VirtualScreenInfo
->bV4Width
= ModeData
->HorizontalResolution
;
305 Private
->VirtualScreenInfo
->bV4Height
= ModeData
->VerticalResolution
;
306 Private
->VirtualScreenInfo
->bV4Planes
= 1;
307 Private
->VirtualScreenInfo
->bV4BitCount
= 32;
311 Private
->VirtualScreenInfo
->bV4V4Compression
= BI_RGB
;
314 // The rest of the allocated memory block is the virtual screen buffer
316 Private
->VirtualScreen
= (RGBQUAD
*) (Private
->VirtualScreenInfo
+ 1);
319 // Use the AdjuctWindowRect fuction to calculate the real width and height
320 // of the new window including the border and caption
324 Rect
.right
= ModeData
->HorizontalResolution
;
325 Rect
.bottom
= ModeData
->VerticalResolution
;
327 Private
->WinNtThunk
->AdjustWindowRect (&Rect
, WS_OVERLAPPEDWINDOW
, 0);
329 Width
= Rect
.right
- Rect
.left
;
330 Height
= Rect
.bottom
- Rect
.top
;
333 // Retrieve the original window position information
335 Private
->WinNtThunk
->GetWindowRect (Private
->WindowHandle
, &Rect
);
338 // Adjust the window size
340 Private
->WinNtThunk
->MoveWindow (Private
->WindowHandle
, Rect
.left
, Rect
.top
, Width
, Height
, TRUE
);
344 NewFillLine
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * ModeData
->HorizontalResolution
);
345 if (NewFillLine
== NULL
) {
346 return EFI_DEVICE_ERROR
;
349 if (Private
->FillLine
!= NULL
) {
350 FreePool (Private
->FillLine
);
353 Private
->FillLine
= NewFillLine
;
366 ModeData
->HorizontalResolution
,
367 ModeData
->VerticalResolution
,
368 ModeData
->HorizontalResolution
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
375 Blt pixels from the rectangle (Width X Height) formed by the BltBuffer
376 onto the graphics screen starting a location (X, Y). (0, 0) is defined as
377 the upper left hand side of the screen. (X, Y) can be outside of the
378 current screen geometry and the BltBuffer will be cliped when it is
379 displayed. X and Y can be negative or positive. If Width or Height is
380 bigger than the current video screen the image will be clipped.
382 @param This Protocol instance pointer.
383 @param X X location on graphics screen.
384 @param Y Y location on the graphics screen.
385 @param Width Width of BltBuffer.
386 @param Height Hight of BltBuffer
387 @param BltOperation Operation to perform on BltBuffer and video memory
388 @param BltBuffer Buffer containing data to blt into video buffer.
389 This buffer has a size of
390 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
391 @param SourceX If the BltOperation is a EfiCopyBlt this is the
392 source of the copy. For other BLT operations this
393 argument is not used.
394 @param SourceX If the BltOperation is a EfiCopyBlt this is the
395 source of the copy. For other BLT operations this
396 argument is not used.
398 @retval EFI_SUCCESS The palette is updated with PaletteArray.
399 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
400 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
404 // TODO: SourceY - add argument and description to function comment
405 // TODO: DestinationX - add argument and description to function comment
406 // TODO: DestinationY - add argument and description to function comment
407 // TODO: Delta - add argument and description to function comment
411 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
412 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
413 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
416 IN UINTN DestinationX
,
417 IN UINTN DestinationY
,
420 IN UINTN Delta OPTIONAL
423 GOP_PRIVATE_DATA
*Private
;
429 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
432 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*FillPixel
;
433 UINT32 VerticalResolution
;
434 UINT32 HorizontalResolution
;
436 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
438 if ((BltOperation
< 0) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
439 return EFI_INVALID_PARAMETER
;
442 if (Width
== 0 || Height
== 0) {
443 return EFI_INVALID_PARAMETER
;
446 // If Delta is zero, then the entire BltBuffer is being used, so Delta
447 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
448 // the number of bytes in each row can be computed.
451 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
455 // We need to fill the Virtual Screen buffer with the blt data.
456 // The virtual screen is upside down, as the first row is the bootom row of
459 VerticalResolution
= This
->Mode
->Info
->VerticalResolution
;
460 HorizontalResolution
= This
->Mode
->Info
->HorizontalResolution
;
461 if (BltOperation
== EfiBltVideoToBltBuffer
) {
464 // Video to BltBuffer: Source is Video, destination is BltBuffer
466 if (SourceY
+ Height
> VerticalResolution
) {
467 return EFI_INVALID_PARAMETER
;
470 if (SourceX
+ Width
> HorizontalResolution
) {
471 return EFI_INVALID_PARAMETER
;
474 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
475 // We would not want a timer based event (Cursor, ...) to come in while we are
476 // doing this operation.
478 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
480 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
481 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ (DstY
* Delta
) + DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
482 VScreen
= &Private
->VirtualScreen
[(VerticalResolution
- SrcY
- 1) * HorizontalResolution
+ SourceX
];
483 CopyMem (Blt
, VScreen
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * Width
);
487 // BltBuffer to Video: Source is BltBuffer, destination is Video
489 if (DestinationY
+ Height
> VerticalResolution
) {
490 return EFI_INVALID_PARAMETER
;
493 if (DestinationX
+ Width
> HorizontalResolution
) {
494 return EFI_INVALID_PARAMETER
;
498 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
499 // We would not want a timer based event (Cursor, ...) to come in while we are
500 // doing this operation.
502 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
504 if (BltOperation
== EfiBltVideoFill
) {
505 FillPixel
= BltBuffer
;
506 for (Index
= 0; Index
< Width
; Index
++) {
507 Private
->FillLine
[Index
] = *FillPixel
;
511 for (Index
= 0; Index
< Height
; Index
++) {
512 if (DestinationY
<= SourceY
) {
513 SrcY
= SourceY
+ Index
;
514 DstY
= DestinationY
+ Index
;
516 SrcY
= SourceY
+ Height
- Index
- 1;
517 DstY
= DestinationY
+ Height
- Index
- 1;
520 VScreen
= &Private
->VirtualScreen
[(VerticalResolution
- DstY
- 1) * HorizontalResolution
+ DestinationX
];
521 switch (BltOperation
) {
522 case EfiBltBufferToVideo
:
523 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ (SrcY
* Delta
) + SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
524 CopyMem (VScreen
, Blt
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
527 case EfiBltVideoToVideo
:
528 VScreenSrc
= &Private
->VirtualScreen
[(VerticalResolution
- SrcY
- 1) * HorizontalResolution
+ SourceX
];
529 CopyMem (VScreen
, VScreenSrc
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
532 case EfiBltVideoFill
:
533 CopyMem (VScreen
, Private
->FillLine
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
539 if (BltOperation
!= EfiBltVideoToBltBuffer
) {
541 // Mark the area we just blted as Invalid so WM_PAINT will update.
543 Rect
.left
= DestinationX
;
544 Rect
.top
= DestinationY
;
545 Rect
.right
= DestinationX
+ Width
;
546 Rect
.bottom
= DestinationY
+ Height
;
547 Private
->WinNtThunk
->InvalidateRect (Private
->WindowHandle
, &Rect
, FALSE
);
550 // Send the WM_PAINT message to the thread that is drawing the window. We
551 // are in the main thread and the window drawing is in a child thread.
552 // There is a child thread per window. We have no CriticalSection or Mutex
553 // since we write the data and the other thread displays the data. While
554 // we may miss some data for a short period of time this is no different than
555 // a write combining on writes to a frame buffer.
558 Private
->WinNtThunk
->UpdateWindow (Private
->WindowHandle
);
561 gBS
->RestoreTPL (OriginalTPL
);
567 // Construction and Destruction functions
577 // TODO: WinNtIo - add argument and description to function comment
578 // TODO: EFI_UNSUPPORTED - add return value to function comment
579 // TODO: EFI_SUCCESS - add return value to function comment
582 IN EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
586 // Check to see if the IO abstraction represents a device type we support.
588 // This would be replaced a check of PCI subsystem ID, etc.
590 if (!CompareGuid (WinNtIo
->TypeGuid
, &gEfiWinNtGopGuid
)) {
591 return EFI_UNSUPPORTED
;
599 Win32 Windows event handler.
603 @return See Win32 Book
606 // TODO: hwnd - add argument and description to function comment
607 // TODO: iMsg - add argument and description to function comment
608 // TODO: wParam - add argument and description to function comment
609 // TODO: lParam - add argument and description to function comment
612 WinNtGopThreadWindowProc (
619 GOP_PRIVATE_DATA
*Private
;
622 PAINTSTRUCT PaintStruct
;
627 // BugBug - if there are two instances of this DLL in memory (such as is
628 // the case for ERM), the correct instance of this function may not be called.
629 // This also means that the address of the mTlsIndex value will be wrong, and
630 // the value may be wrong too.
635 // Use mTlsIndex global to get a Thread Local Storage version of Private.
636 // This works since each Gop protocol has a unique Private data instance and
639 Private
= mWinNt
->TlsGetValue (mTlsIndex
);
640 ASSERT (NULL
!= Private
);
644 Size
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
* Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
* sizeof (RGBQUAD
);
647 // Allocate DIB frame buffer directly from NT for performance enhancement
648 // This buffer is the virtual screen/frame buffer. This buffer is not the
649 // same a a frame buffer. The first fow of this buffer will be the bottom
650 // line of the image. This is an artifact of the way we draw to the screen.
652 Private
->VirtualScreenInfo
= Private
->WinNtThunk
->HeapAlloc (
653 Private
->WinNtThunk
->GetProcessHeap (),
658 Private
->VirtualScreenInfo
->bV4Size
= sizeof (BITMAPV4HEADER
);
659 Private
->VirtualScreenInfo
->bV4Width
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
660 Private
->VirtualScreenInfo
->bV4Height
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
661 Private
->VirtualScreenInfo
->bV4Planes
= 1;
662 Private
->VirtualScreenInfo
->bV4BitCount
= 32;
666 Private
->VirtualScreenInfo
->bV4V4Compression
= BI_RGB
;
667 Private
->VirtualScreen
= (RGBQUAD
*) (Private
->VirtualScreenInfo
+ 1);
672 // I have not found a way to convert hwnd into a Private context. So for
673 // now we use this API to convert hwnd to Private data.
676 Handle
= mWinNt
->BeginPaint (hwnd
, &PaintStruct
);
678 mWinNt
->SetDIBitsToDevice (
679 Handle
, // Destination Device Context
680 0, // Destination X - 0
681 0, // Destination Y - 0
682 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
, // Width
683 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
, // Height
686 0, // DIB Start Scan Line
687 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
, // Number of scan lines
688 Private
->VirtualScreen
, // Address of array of DIB bits
689 (BITMAPINFO
*) Private
->VirtualScreenInfo
, // Address of structure with bitmap info
690 DIB_RGB_COLORS
// RGB or palette indexes
693 mWinNt
->EndPaint (hwnd
, &PaintStruct
);
697 // F10 and the ALT key do not create a WM_KEYDOWN message, thus this special case
698 // WM_SYSKEYDOWN is posted when F10 is pressed or
699 // holds down ALT key and then presses another key.
705 Key
.ScanCode
= SCAN_F10
;
707 GopPrivateAddQ (Private
, Key
);
711 if ((lParam
& GOP_ALT_KEY_PRESSED
) == GOP_ALT_KEY_PRESSED
) {
713 // ALT is pressed with another key pressed
715 WinNtGopConvertParamToEfiKey (Private
, &wParam
, &Key
);
717 if ((lParam
& GOP_EXTENDED_KEY
) == GOP_EXTENDED_KEY
) {
718 Private
->RightAlt
= TRUE
;
720 Private
->LeftAlt
= TRUE
;
723 if (Private
->RightAlt
&& Private
->LeftAlt
) {
724 Private
->LeftAlt
= FALSE
;
728 if (Key
.ScanCode
!= 0) {
730 GopPrivateAddQ (Private
, Key
);
736 if ((lParam
& GOP_ALT_KEY_PRESSED
) == GOP_ALT_KEY_PRESSED
) {
738 // ALT is pressed with another key released
740 WinNtGopConvertParamToEfiKeyShiftState (Private
, &wParam
, FALSE
);
742 // Actually ALT key is still held down here.
743 // Change the ALT key state when another key is released
744 // by user because we did not find a better solution to
745 // get a released ALT key.
747 Private
->RightAlt
= FALSE
;
748 Private
->LeftAlt
= FALSE
;
756 WinNtGopConvertParamToEfiKey (Private
, &wParam
, &Key
);
757 if (Key
.ScanCode
!= 0) {
759 GopPrivateAddQ (Private
, Key
);
765 WinNtGopConvertParamToEfiKeyShiftState (Private
, &wParam
, FALSE
);
770 // The ESC key also generate WM_CHAR.
772 if (wParam
== 0x1B) {
776 for (Index
= 0; Index
< (lParam
& 0xffff); Index
++) {
778 Key
.UnicodeChar
= (CHAR16
) wParam
;
780 GopPrivateAddQ (Private
, Key
);
788 // This close message is issued by user, core is not aware of this,
789 // so don't release the window display resource, just hide the window.
791 Private
->WinNtThunk
->ShowWindow (Private
->WindowHandle
, SW_HIDE
);
795 mWinNt
->DestroyWindow (hwnd
);
796 mWinNt
->PostQuitMessage (0);
798 mWinNt
->HeapFree (Private
->WinNtThunk
->GetProcessHeap (), 0, Private
->VirtualScreenInfo
);
800 mWinNt
->ExitThread (0);
807 return mWinNt
->DefWindowProc (hwnd
, iMsg
, wParam
, lParam
);
812 This thread simulates the end of WinMain () aplication. Each Winow nededs
813 to process it's events. The messages are dispatched to
814 WinNtGopThreadWindowProc ().
815 Be very careful sine WinNtGopThreadWinMain () and WinNtGopThreadWindowProc ()
816 are running in a seperate thread. We have to do this to process the events.
818 @param lpParameter Handle of window to manage.
820 @return if a WM_QUIT message is returned exit.
825 WinNtGopThreadWinMain (
830 GOP_PRIVATE_DATA
*Private
;
834 Private
= (GOP_PRIVATE_DATA
*) lpParameter
;
835 ASSERT (NULL
!= Private
);
838 // Since each thread has unique private data, save the private data in Thread
839 // Local Storage slot. Then the shared global mTlsIndex can be used to get
840 // thread specific context.
842 Private
->WinNtThunk
->TlsSetValue (mTlsIndex
, Private
);
844 Private
->ThreadId
= Private
->WinNtThunk
->GetCurrentThreadId ();
846 Private
->WindowsClass
.cbSize
= sizeof (WNDCLASSEX
);
847 Private
->WindowsClass
.style
= CS_HREDRAW
| CS_VREDRAW
| CS_OWNDC
;
848 Private
->WindowsClass
.lpfnWndProc
= WinNtGopThreadWindowProc
;
849 Private
->WindowsClass
.cbClsExtra
= 0;
850 Private
->WindowsClass
.cbWndExtra
= 0;
851 Private
->WindowsClass
.hInstance
= NULL
;
852 Private
->WindowsClass
.hIcon
= Private
->WinNtThunk
->LoadIcon (NULL
, IDI_APPLICATION
);
853 Private
->WindowsClass
.hCursor
= Private
->WinNtThunk
->LoadCursor (NULL
, IDC_ARROW
);
854 Private
->WindowsClass
.hbrBackground
= (HBRUSH
) COLOR_WINDOW
;
855 Private
->WindowsClass
.lpszMenuName
= NULL
;
856 Private
->WindowsClass
.lpszClassName
= WIN_NT_GOP_CLASS_NAME
;
857 Private
->WindowsClass
.hIconSm
= Private
->WinNtThunk
->LoadIcon (NULL
, IDI_APPLICATION
);
860 // This call will fail after the first time, but thats O.K. since we only need
861 // WIN_NT_GOP_CLASS_NAME to exist to create the window.
863 // Note: Multiple instances of this DLL will use the same instance of this
864 // Class, including the callback function, unless the Class is unregistered and
865 // successfully registered again.
867 Atom
= Private
->WinNtThunk
->RegisterClassEx (&Private
->WindowsClass
);
870 // Setting Rect values to allow for the AdjustWindowRect to provide
871 // us the correct sizes for the client area when doing the CreateWindowEx
874 Rect
.bottom
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
876 Rect
.right
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
878 Private
->WinNtThunk
->AdjustWindowRect (&Rect
, WS_OVERLAPPEDWINDOW
, 0);
880 Private
->WindowHandle
= Private
->WinNtThunk
->CreateWindowEx (
882 WIN_NT_GOP_CLASS_NAME
,
887 Rect
.right
- Rect
.left
,
888 Rect
.bottom
- Rect
.top
,
896 // The reset of this thread is the standard winows program. We need a sperate
897 // thread since we must process the message loop to make windows act like
901 Private
->WinNtThunk
->ShowWindow (Private
->WindowHandle
, SW_SHOW
);
902 Private
->WinNtThunk
->UpdateWindow (Private
->WindowHandle
);
905 // Let the main thread get some work done
907 Private
->WinNtThunk
->ReleaseSemaphore (Private
->ThreadInited
, 1, NULL
);
910 // This is the message loop that all Windows programs need.
912 while (Private
->WinNtThunk
->GetMessage (&Message
, Private
->WindowHandle
, 0, 0)) {
913 Private
->WinNtThunk
->TranslateMessage (&Message
);
914 Private
->WinNtThunk
->DispatchMessage (&Message
);
917 return Message
.wParam
;
922 TODO: Add function description
924 @param Private TODO: add argument description
925 @param HorizontalResolution TODO: add argument description
926 @param VerticalResolution TODO: add argument description
927 @param ColorDepth TODO: add argument description
928 @param RefreshRate TODO: add argument description
930 @return TODO: add return values
934 WinNtGopStartWindow (
935 IN GOP_PRIVATE_DATA
*Private
,
936 IN UINT32 HorizontalResolution
,
937 IN UINT32 VerticalResolution
,
938 IN UINT32 ColorDepth
,
939 IN UINT32 RefreshRate
945 mWinNt
= Private
->WinNtThunk
;
948 // Initialize a Thread Local Storge variable slot. We use TLS to get the
949 // correct Private data instance into the windows thread.
951 if (mTlsIndex
== TLS_OUT_OF_INDEXES
) {
952 ASSERT (0 == mTlsIndexUseCount
);
953 mTlsIndex
= Private
->WinNtThunk
->TlsAlloc ();
957 // always increase the use count!
962 // Register to be notified on exit boot services so we can destroy the window.
964 Status
= gBS
->CreateEvent (
965 EVT_SIGNAL_EXIT_BOOT_SERVICES
,
969 &mGopScreenExitBootServicesEvent
972 Private
->ThreadInited
= Private
->WinNtThunk
->CreateSemaphore (NULL
, 0, 1, NULL
);
973 Private
->ThreadHandle
= Private
->WinNtThunk
->CreateThread (
976 WinNtGopThreadWinMain
,
983 // The other thread has entered the windows message loop so we can
984 // continue our initialization.
986 Private
->WinNtThunk
->WaitForSingleObject (Private
->ThreadInited
, INFINITE
);
987 Private
->WinNtThunk
->CloseHandle (Private
->ThreadInited
);
999 // TODO: Private - add argument and description to function comment
1000 // TODO: EFI_SUCCESS - add return value to function comment
1002 WinNtGopConstructor (
1003 GOP_PRIVATE_DATA
*Private
1006 Private
->ModeData
= mGopModeData
;
1008 Private
->GraphicsOutput
.QueryMode
= WinNtGopQuerytMode
;
1009 Private
->GraphicsOutput
.SetMode
= WinNtGopSetMode
;
1010 Private
->GraphicsOutput
.Blt
= WinNtGopBlt
;
1013 // Allocate buffer for Graphics Output Protocol mode information
1015 Private
->GraphicsOutput
.Mode
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
));
1016 if (Private
->GraphicsOutput
.Mode
== NULL
) {
1017 return EFI_OUT_OF_RESOURCES
;
1019 Private
->GraphicsOutput
.Mode
->Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
1020 if (Private
->GraphicsOutput
.Mode
->Info
== NULL
) {
1021 return EFI_OUT_OF_RESOURCES
;
1024 Private
->GraphicsOutput
.Mode
->MaxMode
= sizeof(mGopModeData
) / sizeof(GOP_MODE_DATA
);
1026 // Till now, we have no idea about the window size.
1028 Private
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
1029 Private
->GraphicsOutput
.Mode
->Info
->Version
= 0;
1030 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
= 0;
1031 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
= 0;
1032 Private
->GraphicsOutput
.Mode
->Info
->PixelFormat
= PixelBltOnly
;
1033 Private
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
1034 Private
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
1035 Private
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
1037 Private
->HardwareNeedsStarting
= TRUE
;
1038 Private
->FillLine
= NULL
;
1040 WinNtGopInitializeSimpleTextInForWindow (Private
);
1052 // TODO: Private - add argument and description to function comment
1053 // TODO: EFI_SUCCESS - add return value to function comment
1055 WinNtGopDestructor (
1056 GOP_PRIVATE_DATA
*Private
1059 UINT32 UnregisterReturn
;
1061 if (!Private
->HardwareNeedsStarting
) {
1063 // BugBug: Shutdown GOP Hardware and any child devices.
1065 Private
->WinNtThunk
->SendMessage (Private
->WindowHandle
, WM_DESTROY
, 0, 0);
1066 Private
->WinNtThunk
->CloseHandle (Private
->ThreadHandle
);
1068 mTlsIndexUseCount
--;
1071 // The callback function for another window could still be called,
1072 // so we need to make sure there are no more users of mTlsIndex.
1074 if (0 == mTlsIndexUseCount
) {
1075 ASSERT (TLS_OUT_OF_INDEXES
!= mTlsIndex
);
1077 Private
->WinNtThunk
->TlsFree (mTlsIndex
);
1078 mTlsIndex
= TLS_OUT_OF_INDEXES
;
1080 UnregisterReturn
= Private
->WinNtThunk
->UnregisterClass (
1081 Private
->WindowsClass
.lpszClassName
,
1082 Private
->WindowsClass
.hInstance
1086 WinNtGopDestroySimpleTextInForWindow (Private
);
1090 // Free graphics output protocol occupied resource
1092 if (Private
->GraphicsOutput
.Mode
!= NULL
) {
1093 if (Private
->GraphicsOutput
.Mode
->Info
!= NULL
) {
1094 FreePool (Private
->GraphicsOutput
.Mode
->Info
);
1096 FreePool (Private
->GraphicsOutput
.Mode
);
1104 This is the GOP screen's callback notification function for exit-boot-services.
1105 All we do here is call WinNtGopDestructor().
1107 @param Event not used
1108 @param Context pointer to the Private structure.
1122 Status
= WinNtGopDestructor (Context
);