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 EFI_EVENT mGopScreenExitBootServicesEvent
;
31 GOP_MODE_DATA mGopModeData
[] = {
41 IN GOP_PRIVATE_DATA
*Private
,
42 IN UINT32 HorizontalResolution
,
43 IN UINT32 VerticalResolution
,
56 WinNtGopConvertParamToEfiKeyShiftState (
57 IN GOP_PRIVATE_DATA
*Private
,
64 // BUGBUG: Only GetAsyncKeyState() and GetKeyState() can distinguish
65 // left and right Ctrl, and Shift key.
66 // Neither of the two is defined in EFI_WIN_NT_THUNK_PROTOCOL.
67 // Therefor, we can not set the correct Shift state here.
70 Private
->LeftShift
= Flag
;
73 Private
->LeftCtrl
= Flag
;
76 Private
->LeftLogo
= Flag
;
79 Private
->RightLogo
= Flag
;
85 // BUGBUG: PrintScreen/SysRq can not trigger WM_KEYDOWN message,
86 // so SySReq shift state is not supported here.
89 Private
->SysReq
= Flag
;
95 WinNtGopConvertParamToEfiKey (
96 IN GOP_PRIVATE_DATA
*Private
,
102 case VK_HOME
: Key
->ScanCode
= SCAN_HOME
; break;
103 case VK_END
: Key
->ScanCode
= SCAN_END
; break;
104 case VK_LEFT
: Key
->ScanCode
= SCAN_LEFT
; break;
105 case VK_RIGHT
: Key
->ScanCode
= SCAN_RIGHT
; break;
106 case VK_UP
: Key
->ScanCode
= SCAN_UP
; break;
107 case VK_DOWN
: Key
->ScanCode
= SCAN_DOWN
; break;
108 case VK_DELETE
: Key
->ScanCode
= SCAN_DELETE
; break;
109 case VK_INSERT
: Key
->ScanCode
= SCAN_INSERT
; break;
110 case VK_PRIOR
: Key
->ScanCode
= SCAN_PAGE_UP
; break;
111 case VK_NEXT
: Key
->ScanCode
= SCAN_PAGE_DOWN
; break;
112 case VK_ESCAPE
: Key
->ScanCode
= SCAN_ESC
; break;
114 case VK_F1
: Key
->ScanCode
= SCAN_F1
; break;
115 case VK_F2
: Key
->ScanCode
= SCAN_F2
; break;
116 case VK_F3
: Key
->ScanCode
= SCAN_F3
; break;
117 case VK_F4
: Key
->ScanCode
= SCAN_F4
; break;
118 case VK_F5
: Key
->ScanCode
= SCAN_F5
; break;
119 case VK_F6
: Key
->ScanCode
= SCAN_F6
; break;
120 case VK_F7
: Key
->ScanCode
= SCAN_F7
; break;
121 case VK_F8
: Key
->ScanCode
= SCAN_F8
; break;
122 case VK_F9
: Key
->ScanCode
= SCAN_F9
; break;
123 case VK_F11
: Key
->ScanCode
= SCAN_F11
; break;
124 case VK_F12
: Key
->ScanCode
= SCAN_F12
; break;
126 case VK_F13
: Key
->ScanCode
= SCAN_F13
; break;
127 case VK_F14
: Key
->ScanCode
= SCAN_F14
; break;
128 case VK_F15
: Key
->ScanCode
= SCAN_F15
; break;
129 case VK_F16
: Key
->ScanCode
= SCAN_F16
; break;
130 case VK_F17
: Key
->ScanCode
= SCAN_F17
; break;
131 case VK_F18
: Key
->ScanCode
= SCAN_F18
; break;
132 case VK_F19
: Key
->ScanCode
= SCAN_F19
; break;
133 case VK_F20
: Key
->ScanCode
= SCAN_F20
; break;
134 case VK_F21
: Key
->ScanCode
= SCAN_F21
; break;
135 case VK_F22
: Key
->ScanCode
= SCAN_F22
; break;
136 case VK_F23
: Key
->ScanCode
= SCAN_F23
; break;
137 case VK_F24
: Key
->ScanCode
= SCAN_F24
; break;
143 Private
->NumLock
= !Private
->NumLock
;
146 Private
->ScrollLock
= !Private
->ScrollLock
;
149 Private
->CapsLock
= !Private
->CapsLock
;
153 WinNtGopConvertParamToEfiKeyShiftState (Private
, wParam
, TRUE
);
158 // GOP Protocol Member Functions
163 Graphics Output protocol interface to get video mode
165 @param This Protocol instance pointer.
166 @param ModeNumber The mode number to return information on.
167 @param Info Caller allocated buffer that returns information
169 @param SizeOfInfo A pointer to the size, in bytes, of the Info
172 @retval EFI_SUCCESS Mode information returned.
173 @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.
174 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
176 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
177 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
183 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
184 IN UINT32 ModeNumber
,
185 OUT UINTN
*SizeOfInfo
,
186 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
189 GOP_PRIVATE_DATA
*Private
;
191 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
193 if (Info
== NULL
|| SizeOfInfo
== NULL
|| (UINTN
) ModeNumber
>= This
->Mode
->MaxMode
) {
194 return EFI_INVALID_PARAMETER
;
197 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
199 return EFI_OUT_OF_RESOURCES
;
202 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
204 (*Info
)->Version
= 0;
205 (*Info
)->HorizontalResolution
= Private
->ModeData
[ModeNumber
].HorizontalResolution
;
206 (*Info
)->VerticalResolution
= Private
->ModeData
[ModeNumber
].VerticalResolution
;
207 (*Info
)->PixelFormat
= PixelBltOnly
;
208 (*Info
)->PixelsPerScanLine
= (*Info
)->HorizontalResolution
;
215 Graphics Output protocol interface to set video mode
217 @param This Protocol instance pointer.
218 @param ModeNumber The mode number to be set.
220 @retval EFI_SUCCESS Graphics mode was changed.
221 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
223 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
229 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
234 GOP_PRIVATE_DATA
*Private
;
235 GOP_MODE_DATA
*ModeData
;
236 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill
;
237 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*NewFillLine
;
243 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
245 if (ModeNumber
>= This
->Mode
->MaxMode
) {
246 return EFI_UNSUPPORTED
;
249 if (ModeNumber
== This
->Mode
->Mode
) {
253 ModeData
= &Private
->ModeData
[ModeNumber
];
254 This
->Mode
->Mode
= ModeNumber
;
255 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
256 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
257 Private
->GraphicsOutput
.Mode
->Info
->PixelsPerScanLine
= ModeData
->HorizontalResolution
;
259 if (Private
->HardwareNeedsStarting
) {
260 Status
= WinNtGopStartWindow (
262 ModeData
->HorizontalResolution
,
263 ModeData
->VerticalResolution
,
264 ModeData
->ColorDepth
,
265 ModeData
->RefreshRate
267 if (EFI_ERROR (Status
)) {
268 return EFI_DEVICE_ERROR
;
271 Private
->HardwareNeedsStarting
= FALSE
;
274 // Change the resolution and resize of the window
278 // Free the old buffer. We do not save the content of the old buffer since the
279 // screen is to be cleared anyway. Clearing the screen is required by the EFI spec.
280 // See UEFI spec -EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode()
282 Private
->WinNtThunk
->HeapFree (Private
->WinNtThunk
->GetProcessHeap (), 0, Private
->VirtualScreenInfo
);
285 // Allocate DIB frame buffer directly from NT for performance enhancement
286 // This buffer is the virtual screen/frame buffer. This buffer is not the
287 // same a a frame buffer. The first row of this buffer will be the bottom
288 // line of the image. This is an artifact of the way we draw to the screen.
290 Size
= ModeData
->HorizontalResolution
* ModeData
->VerticalResolution
* sizeof (RGBQUAD
) + sizeof (BITMAPV4HEADER
);
291 Private
->VirtualScreenInfo
= Private
->WinNtThunk
->HeapAlloc (
292 Private
->WinNtThunk
->GetProcessHeap (),
298 // Update the virtual screen info data structure
300 Private
->VirtualScreenInfo
->bV4Size
= sizeof (BITMAPV4HEADER
);
301 Private
->VirtualScreenInfo
->bV4Width
= ModeData
->HorizontalResolution
;
302 Private
->VirtualScreenInfo
->bV4Height
= ModeData
->VerticalResolution
;
303 Private
->VirtualScreenInfo
->bV4Planes
= 1;
304 Private
->VirtualScreenInfo
->bV4BitCount
= 32;
308 Private
->VirtualScreenInfo
->bV4V4Compression
= BI_RGB
;
311 // The rest of the allocated memory block is the virtual screen buffer
313 Private
->VirtualScreen
= (RGBQUAD
*) (Private
->VirtualScreenInfo
+ 1);
316 // Use the AdjuctWindowRect fuction to calculate the real width and height
317 // of the new window including the border and caption
321 Rect
.right
= ModeData
->HorizontalResolution
;
322 Rect
.bottom
= ModeData
->VerticalResolution
;
324 Private
->WinNtThunk
->AdjustWindowRect (&Rect
, WS_OVERLAPPEDWINDOW
, 0);
326 Width
= Rect
.right
- Rect
.left
;
327 Height
= Rect
.bottom
- Rect
.top
;
330 // Retrieve the original window position information
332 Private
->WinNtThunk
->GetWindowRect (Private
->WindowHandle
, &Rect
);
335 // Adjust the window size
337 Private
->WinNtThunk
->MoveWindow (Private
->WindowHandle
, Rect
.left
, Rect
.top
, Width
, Height
, TRUE
);
341 NewFillLine
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * ModeData
->HorizontalResolution
);
342 if (NewFillLine
== NULL
) {
343 return EFI_DEVICE_ERROR
;
346 if (Private
->FillLine
!= NULL
) {
347 FreePool (Private
->FillLine
);
350 Private
->FillLine
= NewFillLine
;
363 ModeData
->HorizontalResolution
,
364 ModeData
->VerticalResolution
,
365 ModeData
->HorizontalResolution
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
372 Blt pixels from the rectangle (Width X Height) formed by the BltBuffer
373 onto the graphics screen starting a location (X, Y). (0, 0) is defined as
374 the upper left hand side of the screen. (X, Y) can be outside of the
375 current screen geometry and the BltBuffer will be cliped when it is
376 displayed. X and Y can be negative or positive. If Width or Height is
377 bigger than the current video screen the image will be clipped.
379 @param This Protocol instance pointer.
380 @param X X location on graphics screen.
381 @param Y Y location on the graphics screen.
382 @param Width Width of BltBuffer.
383 @param Height Hight of BltBuffer
384 @param BltOperation Operation to perform on BltBuffer and video memory
385 @param BltBuffer Buffer containing data to blt into video buffer.
386 This buffer has a size of
387 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
388 @param SourceX If the BltOperation is a EfiCopyBlt this is the
389 source of the copy. For other BLT operations this
390 argument is not used.
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.
395 @retval EFI_SUCCESS The palette is updated with PaletteArray.
396 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
397 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
401 // TODO: SourceY - add argument and description to function comment
402 // TODO: DestinationX - add argument and description to function comment
403 // TODO: DestinationY - add argument and description to function comment
404 // TODO: Delta - add argument and description to function comment
408 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
409 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
410 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
413 IN UINTN DestinationX
,
414 IN UINTN DestinationY
,
417 IN UINTN Delta OPTIONAL
420 GOP_PRIVATE_DATA
*Private
;
426 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
429 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*FillPixel
;
430 UINT32 VerticalResolution
;
431 UINT32 HorizontalResolution
;
433 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
435 if ((BltOperation
< 0) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
436 return EFI_INVALID_PARAMETER
;
439 if (Width
== 0 || Height
== 0) {
440 return EFI_INVALID_PARAMETER
;
443 // If Delta is zero, then the entire BltBuffer is being used, so Delta
444 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
445 // the number of bytes in each row can be computed.
448 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
452 // We need to fill the Virtual Screen buffer with the blt data.
453 // The virtual screen is upside down, as the first row is the bootom row of
456 VerticalResolution
= This
->Mode
->Info
->VerticalResolution
;
457 HorizontalResolution
= This
->Mode
->Info
->HorizontalResolution
;
458 if (BltOperation
== EfiBltVideoToBltBuffer
) {
461 // Video to BltBuffer: Source is Video, destination is BltBuffer
463 if (SourceY
+ Height
> VerticalResolution
) {
464 return EFI_INVALID_PARAMETER
;
467 if (SourceX
+ Width
> HorizontalResolution
) {
468 return EFI_INVALID_PARAMETER
;
471 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
472 // We would not want a timer based event (Cursor, ...) to come in while we are
473 // doing this operation.
475 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
477 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
478 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ (DstY
* Delta
) + DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
479 VScreen
= &Private
->VirtualScreen
[(VerticalResolution
- SrcY
- 1) * HorizontalResolution
+ SourceX
];
480 CopyMem (Blt
, VScreen
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * Width
);
484 // BltBuffer to Video: Source is BltBuffer, destination is Video
486 if (DestinationY
+ Height
> VerticalResolution
) {
487 return EFI_INVALID_PARAMETER
;
490 if (DestinationX
+ Width
> HorizontalResolution
) {
491 return EFI_INVALID_PARAMETER
;
495 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
496 // We would not want a timer based event (Cursor, ...) to come in while we are
497 // doing this operation.
499 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
501 if (BltOperation
== EfiBltVideoFill
) {
502 FillPixel
= BltBuffer
;
503 for (Index
= 0; Index
< Width
; Index
++) {
504 Private
->FillLine
[Index
] = *FillPixel
;
508 for (Index
= 0; Index
< Height
; Index
++) {
509 if (DestinationY
<= SourceY
) {
510 SrcY
= SourceY
+ Index
;
511 DstY
= DestinationY
+ Index
;
513 SrcY
= SourceY
+ Height
- Index
- 1;
514 DstY
= DestinationY
+ Height
- Index
- 1;
517 VScreen
= &Private
->VirtualScreen
[(VerticalResolution
- DstY
- 1) * HorizontalResolution
+ DestinationX
];
518 switch (BltOperation
) {
519 case EfiBltBufferToVideo
:
520 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ (SrcY
* Delta
) + SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
521 CopyMem (VScreen
, Blt
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
524 case EfiBltVideoToVideo
:
525 VScreenSrc
= &Private
->VirtualScreen
[(VerticalResolution
- SrcY
- 1) * HorizontalResolution
+ SourceX
];
526 CopyMem (VScreen
, VScreenSrc
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
529 case EfiBltVideoFill
:
530 CopyMem (VScreen
, Private
->FillLine
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
536 if (BltOperation
!= EfiBltVideoToBltBuffer
) {
538 // Mark the area we just blted as Invalid so WM_PAINT will update.
540 Rect
.left
= DestinationX
;
541 Rect
.top
= DestinationY
;
542 Rect
.right
= DestinationX
+ Width
;
543 Rect
.bottom
= DestinationY
+ Height
;
544 Private
->WinNtThunk
->InvalidateRect (Private
->WindowHandle
, &Rect
, FALSE
);
547 // Send the WM_PAINT message to the thread that is drawing the window. We
548 // are in the main thread and the window drawing is in a child thread.
549 // There is a child thread per window. We have no CriticalSection or Mutex
550 // since we write the data and the other thread displays the data. While
551 // we may miss some data for a short period of time this is no different than
552 // a write combining on writes to a frame buffer.
555 Private
->WinNtThunk
->UpdateWindow (Private
->WindowHandle
);
558 gBS
->RestoreTPL (OriginalTPL
);
564 // Construction and Destruction functions
574 // TODO: WinNtIo - add argument and description to function comment
575 // TODO: EFI_UNSUPPORTED - add return value to function comment
576 // TODO: EFI_SUCCESS - add return value to function comment
579 IN EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
583 // Check to see if the IO abstraction represents a device type we support.
585 // This would be replaced a check of PCI subsystem ID, etc.
587 if (!CompareGuid (WinNtIo
->TypeGuid
, &gEfiWinNtGopGuid
)) {
588 return EFI_UNSUPPORTED
;
596 Win32 Windows event handler.
600 @return See Win32 Book
603 // TODO: hwnd - add argument and description to function comment
604 // TODO: iMsg - add argument and description to function comment
605 // TODO: wParam - add argument and description to function comment
606 // TODO: lParam - add argument and description to function comment
609 WinNtGopThreadWindowProc (
616 GOP_PRIVATE_DATA
*Private
;
619 PAINTSTRUCT PaintStruct
;
624 // BugBug - if there are two instances of this DLL in memory (such as is
625 // the case for ERM), the correct instance of this function may not be called.
626 // This also means that the address of the mTlsIndex value will be wrong, and
627 // the value may be wrong too.
632 // Use mTlsIndex global to get a Thread Local Storage version of Private.
633 // This works since each Gop protocol has a unique Private data instance and
636 Private
= mWinNt
->TlsGetValue (mTlsIndex
);
637 ASSERT (NULL
!= Private
);
641 Size
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
* Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
* sizeof (RGBQUAD
);
644 // Allocate DIB frame buffer directly from NT for performance enhancement
645 // This buffer is the virtual screen/frame buffer. This buffer is not the
646 // same a a frame buffer. The first fow of this buffer will be the bottom
647 // line of the image. This is an artifact of the way we draw to the screen.
649 Private
->VirtualScreenInfo
= Private
->WinNtThunk
->HeapAlloc (
650 Private
->WinNtThunk
->GetProcessHeap (),
655 Private
->VirtualScreenInfo
->bV4Size
= sizeof (BITMAPV4HEADER
);
656 Private
->VirtualScreenInfo
->bV4Width
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
657 Private
->VirtualScreenInfo
->bV4Height
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
658 Private
->VirtualScreenInfo
->bV4Planes
= 1;
659 Private
->VirtualScreenInfo
->bV4BitCount
= 32;
663 Private
->VirtualScreenInfo
->bV4V4Compression
= BI_RGB
;
664 Private
->VirtualScreen
= (RGBQUAD
*) (Private
->VirtualScreenInfo
+ 1);
669 // I have not found a way to convert hwnd into a Private context. So for
670 // now we use this API to convert hwnd to Private data.
673 Handle
= mWinNt
->BeginPaint (hwnd
, &PaintStruct
);
675 mWinNt
->SetDIBitsToDevice (
676 Handle
, // Destination Device Context
677 0, // Destination X - 0
678 0, // Destination Y - 0
679 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
, // Width
680 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
, // Height
683 0, // DIB Start Scan Line
684 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
, // Number of scan lines
685 Private
->VirtualScreen
, // Address of array of DIB bits
686 (BITMAPINFO
*) Private
->VirtualScreenInfo
, // Address of structure with bitmap info
687 DIB_RGB_COLORS
// RGB or palette indexes
690 mWinNt
->EndPaint (hwnd
, &PaintStruct
);
694 // F10 and the ALT key do not create a WM_KEYDOWN message, thus this special case
695 // WM_SYSKEYDOWN is posted when F10 is pressed or
696 // holds down ALT key and then presses another key.
702 Key
.ScanCode
= SCAN_F10
;
704 GopPrivateAddQ (Private
, Key
);
708 if ((lParam
& GOP_ALT_KEY_PRESSED
) == GOP_ALT_KEY_PRESSED
) {
710 // ALT is pressed with another key pressed
712 WinNtGopConvertParamToEfiKey (Private
, &wParam
, &Key
);
714 if ((lParam
& GOP_EXTENDED_KEY
) == GOP_EXTENDED_KEY
) {
715 Private
->RightAlt
= TRUE
;
717 Private
->LeftAlt
= TRUE
;
720 if (Private
->RightAlt
&& Private
->LeftAlt
) {
721 Private
->LeftAlt
= FALSE
;
725 if (Key
.ScanCode
!= 0) {
727 GopPrivateAddQ (Private
, Key
);
733 if ((lParam
& GOP_ALT_KEY_PRESSED
) == GOP_ALT_KEY_PRESSED
) {
735 // ALT is pressed with another key released
737 WinNtGopConvertParamToEfiKeyShiftState (Private
, &wParam
, FALSE
);
739 // Actually ALT key is still held down here.
740 // Change the ALT key state when another key is released
741 // by user because we did not find a better solution to
742 // get a released ALT key.
744 Private
->RightAlt
= FALSE
;
745 Private
->LeftAlt
= FALSE
;
753 WinNtGopConvertParamToEfiKey (Private
, &wParam
, &Key
);
754 if (Key
.ScanCode
!= 0) {
756 GopPrivateAddQ (Private
, Key
);
762 WinNtGopConvertParamToEfiKeyShiftState (Private
, &wParam
, FALSE
);
767 // The ESC key also generate WM_CHAR.
769 if (wParam
== 0x1B) {
773 for (Index
= 0; Index
< (lParam
& 0xffff); Index
++) {
775 Key
.UnicodeChar
= (CHAR16
) wParam
;
777 GopPrivateAddQ (Private
, Key
);
785 // This close message is issued by user, core is not aware of this,
786 // so don't release the window display resource, just hide the window.
788 Private
->WinNtThunk
->ShowWindow (Private
->WindowHandle
, SW_HIDE
);
792 mWinNt
->DestroyWindow (hwnd
);
793 mWinNt
->PostQuitMessage (0);
795 mWinNt
->HeapFree (Private
->WinNtThunk
->GetProcessHeap (), 0, Private
->VirtualScreenInfo
);
797 mWinNt
->ExitThread (0);
804 return mWinNt
->DefWindowProc (hwnd
, iMsg
, wParam
, lParam
);
809 This thread simulates the end of WinMain () aplication. Each Winow nededs
810 to process it's events. The messages are dispatched to
811 WinNtGopThreadWindowProc ().
812 Be very careful sine WinNtGopThreadWinMain () and WinNtGopThreadWindowProc ()
813 are running in a seperate thread. We have to do this to process the events.
815 @param lpParameter Handle of window to manage.
817 @return if a WM_QUIT message is returned exit.
822 WinNtGopThreadWinMain (
827 GOP_PRIVATE_DATA
*Private
;
831 Private
= (GOP_PRIVATE_DATA
*) lpParameter
;
832 ASSERT (NULL
!= Private
);
835 // Since each thread has unique private data, save the private data in Thread
836 // Local Storage slot. Then the shared global mTlsIndex can be used to get
837 // thread specific context.
839 Private
->WinNtThunk
->TlsSetValue (mTlsIndex
, Private
);
841 Private
->ThreadId
= Private
->WinNtThunk
->GetCurrentThreadId ();
843 Private
->WindowsClass
.cbSize
= sizeof (WNDCLASSEX
);
844 Private
->WindowsClass
.style
= CS_HREDRAW
| CS_VREDRAW
| CS_OWNDC
;
845 Private
->WindowsClass
.lpfnWndProc
= WinNtGopThreadWindowProc
;
846 Private
->WindowsClass
.cbClsExtra
= 0;
847 Private
->WindowsClass
.cbWndExtra
= 0;
848 Private
->WindowsClass
.hInstance
= NULL
;
849 Private
->WindowsClass
.hIcon
= Private
->WinNtThunk
->LoadIcon (NULL
, IDI_APPLICATION
);
850 Private
->WindowsClass
.hCursor
= Private
->WinNtThunk
->LoadCursor (NULL
, IDC_ARROW
);
851 Private
->WindowsClass
.hbrBackground
= (HBRUSH
) COLOR_WINDOW
;
852 Private
->WindowsClass
.lpszMenuName
= NULL
;
853 Private
->WindowsClass
.lpszClassName
= WIN_NT_GOP_CLASS_NAME
;
854 Private
->WindowsClass
.hIconSm
= Private
->WinNtThunk
->LoadIcon (NULL
, IDI_APPLICATION
);
857 // This call will fail after the first time, but thats O.K. since we only need
858 // WIN_NT_GOP_CLASS_NAME to exist to create the window.
860 // Note: Multiple instances of this DLL will use the same instance of this
861 // Class, including the callback function, unless the Class is unregistered and
862 // successfully registered again.
864 Atom
= Private
->WinNtThunk
->RegisterClassEx (&Private
->WindowsClass
);
867 // Setting Rect values to allow for the AdjustWindowRect to provide
868 // us the correct sizes for the client area when doing the CreateWindowEx
871 Rect
.bottom
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
873 Rect
.right
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
875 Private
->WinNtThunk
->AdjustWindowRect (&Rect
, WS_OVERLAPPEDWINDOW
, 0);
877 Private
->WindowHandle
= Private
->WinNtThunk
->CreateWindowEx (
879 WIN_NT_GOP_CLASS_NAME
,
884 Rect
.right
- Rect
.left
,
885 Rect
.bottom
- Rect
.top
,
893 // The reset of this thread is the standard winows program. We need a sperate
894 // thread since we must process the message loop to make windows act like
898 Private
->WinNtThunk
->ShowWindow (Private
->WindowHandle
, SW_SHOW
);
899 Private
->WinNtThunk
->UpdateWindow (Private
->WindowHandle
);
902 // Let the main thread get some work done
904 Private
->WinNtThunk
->ReleaseSemaphore (Private
->ThreadInited
, 1, NULL
);
907 // This is the message loop that all Windows programs need.
909 while (Private
->WinNtThunk
->GetMessage (&Message
, Private
->WindowHandle
, 0, 0)) {
910 Private
->WinNtThunk
->TranslateMessage (&Message
);
911 Private
->WinNtThunk
->DispatchMessage (&Message
);
914 return Message
.wParam
;
919 TODO: Add function description
921 @param Private TODO: add argument description
922 @param HorizontalResolution TODO: add argument description
923 @param VerticalResolution TODO: add argument description
924 @param ColorDepth TODO: add argument description
925 @param RefreshRate TODO: add argument description
927 @return TODO: add return values
931 WinNtGopStartWindow (
932 IN GOP_PRIVATE_DATA
*Private
,
933 IN UINT32 HorizontalResolution
,
934 IN UINT32 VerticalResolution
,
935 IN UINT32 ColorDepth
,
936 IN UINT32 RefreshRate
942 mWinNt
= Private
->WinNtThunk
;
945 // Initialize a Thread Local Storge variable slot. We use TLS to get the
946 // correct Private data instance into the windows thread.
948 if (mTlsIndex
== TLS_OUT_OF_INDEXES
) {
949 ASSERT (0 == mTlsIndexUseCount
);
950 mTlsIndex
= Private
->WinNtThunk
->TlsAlloc ();
954 // always increase the use count!
959 // Register to be notified on exit boot services so we can destroy the window.
961 Status
= gBS
->CreateEvent (
962 EVT_SIGNAL_EXIT_BOOT_SERVICES
,
966 &mGopScreenExitBootServicesEvent
969 Private
->ThreadInited
= Private
->WinNtThunk
->CreateSemaphore (NULL
, 0, 1, NULL
);
970 Private
->ThreadHandle
= Private
->WinNtThunk
->CreateThread (
973 WinNtGopThreadWinMain
,
980 // The other thread has entered the windows message loop so we can
981 // continue our initialization.
983 Private
->WinNtThunk
->WaitForSingleObject (Private
->ThreadInited
, INFINITE
);
984 Private
->WinNtThunk
->CloseHandle (Private
->ThreadInited
);
996 // TODO: Private - add argument and description to function comment
997 // TODO: EFI_SUCCESS - add return value to function comment
999 WinNtGopConstructor (
1000 GOP_PRIVATE_DATA
*Private
1003 Private
->ModeData
= mGopModeData
;
1005 Private
->GraphicsOutput
.QueryMode
= WinNtGopQuerytMode
;
1006 Private
->GraphicsOutput
.SetMode
= WinNtGopSetMode
;
1007 Private
->GraphicsOutput
.Blt
= WinNtGopBlt
;
1010 // Allocate buffer for Graphics Output Protocol mode information
1012 Private
->GraphicsOutput
.Mode
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
));
1013 if (Private
->GraphicsOutput
.Mode
== NULL
) {
1014 return EFI_OUT_OF_RESOURCES
;
1016 Private
->GraphicsOutput
.Mode
->Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
1017 if (Private
->GraphicsOutput
.Mode
->Info
== NULL
) {
1018 return EFI_OUT_OF_RESOURCES
;
1021 Private
->GraphicsOutput
.Mode
->MaxMode
= sizeof(mGopModeData
) / sizeof(GOP_MODE_DATA
);
1023 // Till now, we have no idea about the window size.
1025 Private
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
1026 Private
->GraphicsOutput
.Mode
->Info
->Version
= 0;
1027 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
= 0;
1028 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
= 0;
1029 Private
->GraphicsOutput
.Mode
->Info
->PixelFormat
= PixelBltOnly
;
1030 Private
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
1031 Private
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
;
1032 Private
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
1034 Private
->HardwareNeedsStarting
= TRUE
;
1035 Private
->FillLine
= NULL
;
1037 WinNtGopInitializeSimpleTextInForWindow (Private
);
1049 // TODO: Private - add argument and description to function comment
1050 // TODO: EFI_SUCCESS - add return value to function comment
1052 WinNtGopDestructor (
1053 GOP_PRIVATE_DATA
*Private
1056 UINT32 UnregisterReturn
;
1058 if (!Private
->HardwareNeedsStarting
) {
1060 // BugBug: Shutdown GOP Hardware and any child devices.
1062 Private
->WinNtThunk
->SendMessage (Private
->WindowHandle
, WM_DESTROY
, 0, 0);
1063 Private
->WinNtThunk
->CloseHandle (Private
->ThreadHandle
);
1065 mTlsIndexUseCount
--;
1068 // The callback function for another window could still be called,
1069 // so we need to make sure there are no more users of mTlsIndex.
1071 if (0 == mTlsIndexUseCount
) {
1072 ASSERT (TLS_OUT_OF_INDEXES
!= mTlsIndex
);
1074 Private
->WinNtThunk
->TlsFree (mTlsIndex
);
1075 mTlsIndex
= TLS_OUT_OF_INDEXES
;
1077 UnregisterReturn
= Private
->WinNtThunk
->UnregisterClass (
1078 Private
->WindowsClass
.lpszClassName
,
1079 Private
->WindowsClass
.hInstance
1083 WinNtGopDestroySimpleTextInForWindow (Private
);
1087 // Free graphics output protocol occupied resource
1089 if (Private
->GraphicsOutput
.Mode
!= NULL
) {
1090 if (Private
->GraphicsOutput
.Mode
->Info
!= NULL
) {
1091 FreePool (Private
->GraphicsOutput
.Mode
->Info
);
1093 FreePool (Private
->GraphicsOutput
.Mode
);
1101 This is the GOP screen's callback notification function for exit-boot-services.
1102 All we do here is call WinNtGopDestructor().
1104 @param Event not used
1105 @param Context pointer to the Private structure.
1118 Status
= WinNtGopDestructor (Context
);