]> git.proxmox.com Git - mirror_edk2.git/blame - Nt32Pkg/WinNtGopDxe/WinNtGopScreen.c
Fix a bug that prevents Fat driver being unloaded successfully.
[mirror_edk2.git] / Nt32Pkg / WinNtGopDxe / WinNtGopScreen.c
CommitLineData
c9fc89a3 1/** @file\r
2\r
f66a43b2 3Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
8f2a5f80 4This program and the accompanying materials\r
c9fc89a3 5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 WinNtGopScreen.c\r
15\r
16Abstract:\r
17\r
18 This file produces the graphics abstration of GOP. It is called by\r
8a7d75b0 19 WinNtGopDriver.c file which deals with the UEFI 2.0 driver model.\r
c9fc89a3 20 This file just does graphics.\r
21\r
22\r
23**/\r
c9fc89a3 24\r
25#include "WinNtGop.h"\r
26\r
27EFI_WIN_NT_THUNK_PROTOCOL *mWinNt;\r
28DWORD mTlsIndex = TLS_OUT_OF_INDEXES;\r
29DWORD mTlsIndexUseCount = 0; // lets us know when we can free mTlsIndex.\r
78e570b6 30EFI_EVENT mGopScreenExitBootServicesEvent;\r
c9fc89a3 31GOP_MODE_DATA mGopModeData[] = {\r
32 {800, 600, 0, 0},\r
33 {640, 480, 0, 0},\r
34 {720, 400, 0, 0},\r
35 {1024, 768, 0, 0},\r
36 {1280, 1024, 0, 0}\r
37 };\r
38\r
39EFI_STATUS\r
40WinNtGopStartWindow (\r
41 IN GOP_PRIVATE_DATA *Private,\r
42 IN UINT32 HorizontalResolution,\r
43 IN UINT32 VerticalResolution,\r
44 IN UINT32 ColorDepth,\r
45 IN UINT32 RefreshRate\r
46 );\r
47\r
c9fc89a3 48VOID\r
49EFIAPI\r
50KillNtGopThread (\r
51 IN EFI_EVENT Event,\r
52 IN VOID *Context\r
53 );\r
54\r
df7499fc 55BOOLEAN\r
62cf113f 56WinNtGopConvertParamToEfiKeyShiftState (\r
57 IN GOP_PRIVATE_DATA *Private,\r
58 IN WPARAM *wParam,\r
df7499fc 59 IN LPARAM *lParam,\r
62cf113f 60 IN BOOLEAN Flag\r
61 )\r
62{\r
63 switch (*wParam) {\r
64 //\r
65 // BUGBUG: Only GetAsyncKeyState() and GetKeyState() can distinguish\r
df7499fc 66 // left and right Ctrl, and Shift key.\r
67 // Neither of the two is defined in EFI_WIN_NT_THUNK_PROTOCOL.\r
62cf113f 68 // Therefor, we can not set the correct Shift state here.\r
df7499fc 69 //\r
70 case VK_SHIFT:\r
71 if ((*lParam & GOP_EXTENDED_KEY) == GOP_EXTENDED_KEY) {\r
72 Private->RightShift = Flag;\r
73 } else {\r
74 Private->LeftShift = Flag;\r
75 }\r
76 return TRUE;\r
77\r
78 case VK_LSHIFT:\r
79 Private->LeftShift = Flag;\r
80 return TRUE;\r
81\r
82 case VK_RSHIFT:\r
83 Private->RightShift = Flag;\r
84 return TRUE;\r
85\r
62cf113f 86 case VK_CONTROL:\r
df7499fc 87 if ((*lParam & GOP_EXTENDED_KEY) == GOP_EXTENDED_KEY) {\r
88 Private->RightCtrl= Flag;\r
89 } else {\r
90 Private->LeftCtrl = Flag;\r
91 }\r
92 return TRUE;\r
93\r
94 case VK_LCONTROL:\r
95 Private->LeftCtrl = Flag;\r
96 return TRUE;\r
97\r
98 case VK_RCONTROL:\r
99 Private->RightCtrl = Flag;\r
100 return TRUE;\r
101\r
102 case VK_LWIN:\r
62cf113f 103 Private->LeftLogo = Flag;\r
df7499fc 104 return TRUE;\r
105\r
106 case VK_RWIN:\r
62cf113f 107 Private->RightLogo = Flag;\r
df7499fc 108 return TRUE;\r
109\r
110 case VK_APPS:\r
62cf113f 111 Private->Menu = Flag;\r
df7499fc 112 return TRUE;\r
62cf113f 113 //\r
114 // BUGBUG: PrintScreen/SysRq can not trigger WM_KEYDOWN message,\r
115 // so SySReq shift state is not supported here.\r
116 //\r
df7499fc 117 case VK_PRINT:\r
62cf113f 118 Private->SysReq = Flag;\r
df7499fc 119 return TRUE;\r
120 //\r
121 // For Alt Keystroke.\r
122 //\r
123 case VK_MENU:\r
124 if ((*lParam & GOP_EXTENDED_KEY) == GOP_EXTENDED_KEY) {\r
125 Private->RightAlt = Flag;\r
126 } else {\r
127 Private->LeftAlt = Flag;\r
128 }\r
129 return TRUE;\r
130\r
131 default:\r
132 return FALSE;\r
62cf113f 133 }\r
134}\r
135\r
df7499fc 136BOOLEAN\r
62cf113f 137WinNtGopConvertParamToEfiKey (\r
138 IN GOP_PRIVATE_DATA *Private,\r
139 IN WPARAM *wParam,\r
df7499fc 140 IN LPARAM *lParam,\r
62cf113f 141 IN EFI_INPUT_KEY *Key\r
142 )\r
143{\r
df7499fc 144 BOOLEAN Flag;\r
145 Flag = FALSE;\r
62cf113f 146 switch (*wParam) {\r
df7499fc 147 case VK_HOME: Key->ScanCode = SCAN_HOME; Flag = TRUE; break;\r
148 case VK_END: Key->ScanCode = SCAN_END; Flag = TRUE; break;\r
149 case VK_LEFT: Key->ScanCode = SCAN_LEFT; Flag = TRUE; break;\r
150 case VK_RIGHT: Key->ScanCode = SCAN_RIGHT; Flag = TRUE; break;\r
151 case VK_UP: Key->ScanCode = SCAN_UP; Flag = TRUE; break;\r
152 case VK_DOWN: Key->ScanCode = SCAN_DOWN; Flag = TRUE; break;\r
153 case VK_DELETE: Key->ScanCode = SCAN_DELETE; Flag = TRUE; break;\r
154 case VK_INSERT: Key->ScanCode = SCAN_INSERT; Flag = TRUE; break;\r
155 case VK_PRIOR: Key->ScanCode = SCAN_PAGE_UP; Flag = TRUE; break;\r
156 case VK_NEXT: Key->ScanCode = SCAN_PAGE_DOWN; Flag = TRUE; break;\r
157 case VK_ESCAPE: Key->ScanCode = SCAN_ESC; Flag = TRUE; break;\r
158\r
159 case VK_F1: Key->ScanCode = SCAN_F1; Flag = TRUE; break;\r
160 case VK_F2: Key->ScanCode = SCAN_F2; Flag = TRUE; break;\r
161 case VK_F3: Key->ScanCode = SCAN_F3; Flag = TRUE; break;\r
162 case VK_F4: Key->ScanCode = SCAN_F4; Flag = TRUE; break;\r
163 case VK_F5: Key->ScanCode = SCAN_F5; Flag = TRUE; break;\r
164 case VK_F6: Key->ScanCode = SCAN_F6; Flag = TRUE; break;\r
165 case VK_F7: Key->ScanCode = SCAN_F7; Flag = TRUE; break;\r
166 case VK_F8: Key->ScanCode = SCAN_F8; Flag = TRUE; break;\r
167 case VK_F9: Key->ScanCode = SCAN_F9; Flag = TRUE; break;\r
168 case VK_F11: Key->ScanCode = SCAN_F11; Flag = TRUE; break;\r
169 case VK_F12: Key->ScanCode = SCAN_F12; Flag = TRUE; break;\r
170\r
171 case VK_F13: Key->ScanCode = SCAN_F13; Flag = TRUE; break;\r
172 case VK_F14: Key->ScanCode = SCAN_F14; Flag = TRUE; break;\r
173 case VK_F15: Key->ScanCode = SCAN_F15; Flag = TRUE; break;\r
174 case VK_F16: Key->ScanCode = SCAN_F16; Flag = TRUE; break;\r
175 case VK_F17: Key->ScanCode = SCAN_F17; Flag = TRUE; break;\r
176 case VK_F18: Key->ScanCode = SCAN_F18; Flag = TRUE; break;\r
177 case VK_F19: Key->ScanCode = SCAN_F19; Flag = TRUE; break;\r
178 case VK_F20: Key->ScanCode = SCAN_F20; Flag = TRUE; break;\r
179 case VK_F21: Key->ScanCode = SCAN_F21; Flag = TRUE; break;\r
180 case VK_F22: Key->ScanCode = SCAN_F22; Flag = TRUE; break;\r
181 case VK_F23: Key->ScanCode = SCAN_F23; Flag = TRUE; break;\r
182 case VK_F24: Key->ScanCode = SCAN_F24; Flag = TRUE; break;\r
183 case VK_PAUSE: Key->ScanCode = SCAN_PAUSE; Flag = TRUE; break;\r
62cf113f 184\r
185 //\r
186 // Set toggle state\r
df7499fc 187 //\r
188 case VK_NUMLOCK:\r
a00ec39b 189 Private->NumLock = (BOOLEAN)(!Private->NumLock);\r
df7499fc 190 Flag = TRUE;\r
62cf113f 191 break;\r
192 case VK_SCROLL:\r
a00ec39b 193 Private->ScrollLock = (BOOLEAN)(!Private->ScrollLock);\r
df7499fc 194 Flag = TRUE;\r
195 break;\r
62cf113f 196 case VK_CAPITAL:\r
a00ec39b 197 Private->CapsLock = (BOOLEAN)(!Private->CapsLock);\r
df7499fc 198 Flag = TRUE;\r
199 break;\r
62cf113f 200 }\r
201 \r
df7499fc 202 return (WinNtGopConvertParamToEfiKeyShiftState (Private, wParam, lParam, TRUE)) == TRUE ? TRUE : Flag;\r
62cf113f 203}\r
204\r
205\r
c9fc89a3 206//\r
207// GOP Protocol Member Functions\r
208//\r
209\r
210\r
211/**\r
212 Graphics Output protocol interface to get video mode\r
213\r
214 @param This Protocol instance pointer.\r
215 @param ModeNumber The mode number to return information on.\r
216 @param Info Caller allocated buffer that returns information\r
217 about ModeNumber.\r
218 @param SizeOfInfo A pointer to the size, in bytes, of the Info\r
219 buffer.\r
220\r
221 @retval EFI_SUCCESS Mode information returned.\r
222 @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.\r
223 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the\r
224 video mode.\r
225 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()\r
226 @retval EFI_INVALID_PARAMETER One of the input args was NULL.\r
227\r
228**/\r
229EFI_STATUS\r
230EFIAPI\r
231WinNtGopQuerytMode (\r
232 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
233 IN UINT32 ModeNumber,\r
234 OUT UINTN *SizeOfInfo,\r
235 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
236 )\r
237{\r
238 GOP_PRIVATE_DATA *Private;\r
239\r
240 Private = GOP_PRIVATE_DATA_FROM_THIS (This);\r
241\r
242 if (Info == NULL || SizeOfInfo == NULL || (UINTN) ModeNumber >= This->Mode->MaxMode) {\r
243 return EFI_INVALID_PARAMETER;\r
244 }\r
245\r
246 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
247 if (*Info == NULL) {\r
248 return EFI_OUT_OF_RESOURCES;\r
249 }\r
250\r
251 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
252\r
253 (*Info)->Version = 0;\r
254 (*Info)->HorizontalResolution = Private->ModeData[ModeNumber].HorizontalResolution;\r
255 (*Info)->VerticalResolution = Private->ModeData[ModeNumber].VerticalResolution;\r
62cf113f 256 (*Info)->PixelFormat = PixelBltOnly;\r
c9fc89a3 257 (*Info)->PixelsPerScanLine = (*Info)->HorizontalResolution;\r
258\r
259 return EFI_SUCCESS;\r
260}\r
261\r
262\r
263/**\r
264 Graphics Output protocol interface to set video mode\r
265\r
266 @param This Protocol instance pointer.\r
267 @param ModeNumber The mode number to be set.\r
268\r
269 @retval EFI_SUCCESS Graphics mode was changed.\r
270 @retval EFI_DEVICE_ERROR The device had an error and could not complete the\r
271 request.\r
272 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.\r
273\r
274**/\r
275EFI_STATUS\r
276EFIAPI\r
277WinNtGopSetMode (\r
278 IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,\r
279 IN UINT32 ModeNumber\r
280 )\r
281{\r
282 EFI_STATUS Status;\r
283 GOP_PRIVATE_DATA *Private;\r
284 GOP_MODE_DATA *ModeData;\r
285 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill;\r
286 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *NewFillLine;\r
287 RECT Rect;\r
288 UINTN Size;\r
289 UINTN Width;\r
290 UINTN Height;\r
291\r
292 Private = GOP_PRIVATE_DATA_FROM_THIS (This);\r
293\r
294 if (ModeNumber >= This->Mode->MaxMode) {\r
295 return EFI_UNSUPPORTED;\r
296 }\r
297\r
c9fc89a3 298 ModeData = &Private->ModeData[ModeNumber];\r
299 This->Mode->Mode = ModeNumber;\r
300 Private->GraphicsOutput.Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
301 Private->GraphicsOutput.Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
302 Private->GraphicsOutput.Mode->Info->PixelsPerScanLine = ModeData->HorizontalResolution;\r
303\r
304 if (Private->HardwareNeedsStarting) {\r
305 Status = WinNtGopStartWindow (\r
306 Private,\r
307 ModeData->HorizontalResolution,\r
308 ModeData->VerticalResolution,\r
309 ModeData->ColorDepth,\r
310 ModeData->RefreshRate\r
311 );\r
312 if (EFI_ERROR (Status)) {\r
313 return EFI_DEVICE_ERROR;\r
314 }\r
315\r
316 Private->HardwareNeedsStarting = FALSE;\r
317 } else {\r
318 //\r
319 // Change the resolution and resize of the window\r
320 //\r
321\r
322 //\r
323 // Free the old buffer. We do not save the content of the old buffer since the\r
324 // screen is to be cleared anyway. Clearing the screen is required by the EFI spec.\r
325 // See UEFI spec -EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode()\r
326 //\r
327 Private->WinNtThunk->HeapFree (Private->WinNtThunk->GetProcessHeap (), 0, Private->VirtualScreenInfo);\r
328\r
329 //\r
330 // Allocate DIB frame buffer directly from NT for performance enhancement\r
331 // This buffer is the virtual screen/frame buffer. This buffer is not the\r
332 // same a a frame buffer. The first row of this buffer will be the bottom\r
333 // line of the image. This is an artifact of the way we draw to the screen.\r
334 //\r
335 Size = ModeData->HorizontalResolution * ModeData->VerticalResolution * sizeof (RGBQUAD) + sizeof (BITMAPV4HEADER);\r
336 Private->VirtualScreenInfo = Private->WinNtThunk->HeapAlloc (\r
337 Private->WinNtThunk->GetProcessHeap (),\r
338 HEAP_ZERO_MEMORY,\r
339 Size\r
340 );\r
341\r
342 //\r
343 // Update the virtual screen info data structure\r
344 //\r
345 Private->VirtualScreenInfo->bV4Size = sizeof (BITMAPV4HEADER);\r
346 Private->VirtualScreenInfo->bV4Width = ModeData->HorizontalResolution;\r
347 Private->VirtualScreenInfo->bV4Height = ModeData->VerticalResolution;\r
348 Private->VirtualScreenInfo->bV4Planes = 1;\r
349 Private->VirtualScreenInfo->bV4BitCount = 32;\r
350 //\r
351 // uncompressed\r
352 //\r
353 Private->VirtualScreenInfo->bV4V4Compression = BI_RGB;\r
354\r
355 //\r
356 // The rest of the allocated memory block is the virtual screen buffer\r
357 //\r
358 Private->VirtualScreen = (RGBQUAD *) (Private->VirtualScreenInfo + 1);\r
359\r
360 //\r
361 // Use the AdjuctWindowRect fuction to calculate the real width and height\r
362 // of the new window including the border and caption\r
363 //\r
364 Rect.left = 0;\r
365 Rect.top = 0;\r
366 Rect.right = ModeData->HorizontalResolution;\r
367 Rect.bottom = ModeData->VerticalResolution;\r
368\r
369 Private->WinNtThunk->AdjustWindowRect (&Rect, WS_OVERLAPPEDWINDOW, 0);\r
370\r
371 Width = Rect.right - Rect.left;\r
372 Height = Rect.bottom - Rect.top;\r
373\r
374 //\r
375 // Retrieve the original window position information\r
376 //\r
377 Private->WinNtThunk->GetWindowRect (Private->WindowHandle, &Rect);\r
378\r
379 //\r
380 // Adjust the window size\r
381 //\r
f66a43b2 382 Private->WinNtThunk->MoveWindow (Private->WindowHandle, Rect.left, Rect.top, (INT32)Width, (INT32)Height, TRUE);\r
c9fc89a3 383\r
384 }\r
385\r
386 NewFillLine = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ModeData->HorizontalResolution);\r
387 if (NewFillLine == NULL) {\r
388 return EFI_DEVICE_ERROR;\r
389 }\r
390\r
391 if (Private->FillLine != NULL) {\r
392 FreePool (Private->FillLine);\r
393 }\r
394\r
395 Private->FillLine = NewFillLine;\r
396\r
397 Fill.Red = 0x00;\r
398 Fill.Green = 0x00;\r
399 Fill.Blue = 0x00;\r
400 This->Blt (\r
401 This,\r
402 &Fill,\r
403 EfiBltVideoFill,\r
404 0,\r
405 0,\r
406 0,\r
407 0,\r
408 ModeData->HorizontalResolution,\r
409 ModeData->VerticalResolution,\r
410 ModeData->HorizontalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
411 );\r
412 return EFI_SUCCESS;\r
413}\r
414\r
415\r
416/**\r
417 Blt pixels from the rectangle (Width X Height) formed by the BltBuffer\r
418 onto the graphics screen starting a location (X, Y). (0, 0) is defined as\r
419 the upper left hand side of the screen. (X, Y) can be outside of the\r
420 current screen geometry and the BltBuffer will be cliped when it is\r
421 displayed. X and Y can be negative or positive. If Width or Height is\r
422 bigger than the current video screen the image will be clipped.\r
423\r
424 @param This Protocol instance pointer.\r
425 @param X X location on graphics screen.\r
426 @param Y Y location on the graphics screen.\r
427 @param Width Width of BltBuffer.\r
428 @param Height Hight of BltBuffer\r
429 @param BltOperation Operation to perform on BltBuffer and video memory\r
430 @param BltBuffer Buffer containing data to blt into video buffer.\r
431 This buffer has a size of\r
432 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
433 @param SourceX If the BltOperation is a EfiCopyBlt this is the\r
434 source of the copy. For other BLT operations this\r
435 argument is not used.\r
436 @param SourceX If the BltOperation is a EfiCopyBlt this is the\r
437 source of the copy. For other BLT operations this\r
438 argument is not used.\r
439\r
440 @retval EFI_SUCCESS The palette is updated with PaletteArray.\r
441 @retval EFI_INVALID_PARAMETER BltOperation is not valid.\r
442 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video\r
443 buffer.\r
444\r
445**/\r
446// TODO: SourceY - add argument and description to function comment\r
447// TODO: DestinationX - add argument and description to function comment\r
448// TODO: DestinationY - add argument and description to function comment\r
449// TODO: Delta - add argument and description to function comment\r
450EFI_STATUS\r
451EFIAPI\r
452WinNtGopBlt (\r
453 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
454 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
455 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
456 IN UINTN SourceX,\r
457 IN UINTN SourceY,\r
458 IN UINTN DestinationX,\r
459 IN UINTN DestinationY,\r
460 IN UINTN Width,\r
461 IN UINTN Height,\r
462 IN UINTN Delta OPTIONAL\r
463 )\r
464{\r
465 GOP_PRIVATE_DATA *Private;\r
466 EFI_TPL OriginalTPL;\r
467 UINTN DstY;\r
468 UINTN SrcY;\r
469 RGBQUAD *VScreen;\r
470 RGBQUAD *VScreenSrc;\r
471 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
472 UINTN Index;\r
473 RECT Rect;\r
474 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *FillPixel;\r
475 UINT32 VerticalResolution;\r
476 UINT32 HorizontalResolution;\r
477\r
478 Private = GOP_PRIVATE_DATA_FROM_THIS (This);\r
479\r
480 if ((BltOperation < 0) || (BltOperation >= EfiGraphicsOutputBltOperationMax)) {\r
481 return EFI_INVALID_PARAMETER;\r
482 }\r
483\r
484 if (Width == 0 || Height == 0) {\r
485 return EFI_INVALID_PARAMETER;\r
486 }\r
487 //\r
488 // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
489 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
490 // the number of bytes in each row can be computed.\r
491 //\r
492 if (Delta == 0) {\r
493 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
494 }\r
495\r
496 //\r
497 // We need to fill the Virtual Screen buffer with the blt data.\r
498 // The virtual screen is upside down, as the first row is the bootom row of\r
499 // the image.\r
500 //\r
501 VerticalResolution = This->Mode->Info->VerticalResolution;\r
502 HorizontalResolution = This->Mode->Info->HorizontalResolution;\r
503 if (BltOperation == EfiBltVideoToBltBuffer) {\r
504\r
505 //\r
506 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
507 //\r
508 if (SourceY + Height > VerticalResolution) {\r
509 return EFI_INVALID_PARAMETER;\r
510 }\r
511\r
512 if (SourceX + Width > HorizontalResolution) {\r
513 return EFI_INVALID_PARAMETER;\r
514 }\r
515 //\r
516 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
517 // We would not want a timer based event (Cursor, ...) to come in while we are\r
518 // doing this operation.\r
519 //\r
520 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
521\r
522 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {\r
523 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + (DstY * Delta) + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
524 VScreen = &Private->VirtualScreen[(VerticalResolution - SrcY - 1) * HorizontalResolution + SourceX];\r
525 CopyMem (Blt, VScreen, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * Width);\r
526 }\r
527 } else {\r
528 //\r
529 // BltBuffer to Video: Source is BltBuffer, destination is Video\r
530 //\r
531 if (DestinationY + Height > VerticalResolution) {\r
532 return EFI_INVALID_PARAMETER;\r
533 }\r
534\r
535 if (DestinationX + Width > HorizontalResolution) {\r
536 return EFI_INVALID_PARAMETER;\r
537 }\r
538\r
539 //\r
540 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
541 // We would not want a timer based event (Cursor, ...) to come in while we are\r
542 // doing this operation.\r
543 //\r
544 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
545\r
546 if (BltOperation == EfiBltVideoFill) {\r
547 FillPixel = BltBuffer;\r
548 for (Index = 0; Index < Width; Index++) {\r
549 Private->FillLine[Index] = *FillPixel;\r
550 }\r
551 }\r
552\r
553 for (Index = 0; Index < Height; Index++) {\r
554 if (DestinationY <= SourceY) {\r
555 SrcY = SourceY + Index;\r
556 DstY = DestinationY + Index;\r
557 } else {\r
558 SrcY = SourceY + Height - Index - 1;\r
559 DstY = DestinationY + Height - Index - 1;\r
560 }\r
561\r
562 VScreen = &Private->VirtualScreen[(VerticalResolution - DstY - 1) * HorizontalResolution + DestinationX];\r
563 switch (BltOperation) {\r
564 case EfiBltBufferToVideo:\r
565 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + (SrcY * Delta) + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
566 CopyMem (VScreen, Blt, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
567 break;\r
568\r
569 case EfiBltVideoToVideo:\r
570 VScreenSrc = &Private->VirtualScreen[(VerticalResolution - SrcY - 1) * HorizontalResolution + SourceX];\r
571 CopyMem (VScreen, VScreenSrc, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
572 break;\r
573\r
574 case EfiBltVideoFill:\r
575 CopyMem (VScreen, Private->FillLine, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
576 break;\r
577 }\r
578 }\r
579 }\r
580\r
581 if (BltOperation != EfiBltVideoToBltBuffer) {\r
582 //\r
583 // Mark the area we just blted as Invalid so WM_PAINT will update.\r
584 //\r
f66a43b2
JM
585 Rect.left = (LONG)DestinationX;\r
586 Rect.top = (LONG)DestinationY;\r
587 Rect.right = (LONG)(DestinationX + Width);\r
588 Rect.bottom = (LONG)(DestinationY + Height);\r
c9fc89a3 589 Private->WinNtThunk->InvalidateRect (Private->WindowHandle, &Rect, FALSE);\r
590\r
591 //\r
592 // Send the WM_PAINT message to the thread that is drawing the window. We\r
593 // are in the main thread and the window drawing is in a child thread.\r
594 // There is a child thread per window. We have no CriticalSection or Mutex\r
595 // since we write the data and the other thread displays the data. While\r
596 // we may miss some data for a short period of time this is no different than\r
597 // a write combining on writes to a frame buffer.\r
598 //\r
599\r
600 Private->WinNtThunk->UpdateWindow (Private->WindowHandle);\r
601 }\r
602\r
603 gBS->RestoreTPL (OriginalTPL);\r
604\r
605 return EFI_SUCCESS;\r
606}\r
607\r
608//\r
609// Construction and Destruction functions\r
610//\r
611\r
612\r
613/**\r
614\r
615\r
616 @return None\r
617\r
618**/\r
619// TODO: WinNtIo - add argument and description to function comment\r
620// TODO: EFI_UNSUPPORTED - add return value to function comment\r
621// TODO: EFI_SUCCESS - add return value to function comment\r
622EFI_STATUS\r
623WinNtGopSupported (\r
624 IN EFI_WIN_NT_IO_PROTOCOL *WinNtIo\r
625 )\r
626{\r
627 //\r
628 // Check to see if the IO abstraction represents a device type we support.\r
629 //\r
630 // This would be replaced a check of PCI subsystem ID, etc.\r
631 //\r
632 if (!CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtGopGuid)) {\r
633 return EFI_UNSUPPORTED;\r
634 }\r
635\r
636 return EFI_SUCCESS;\r
637}\r
638\r
639\r
640/**\r
641 Win32 Windows event handler.\r
642\r
643 See Win32 Book\r
644\r
645 @return See Win32 Book\r
646\r
647**/\r
648// TODO: hwnd - add argument and description to function comment\r
649// TODO: iMsg - add argument and description to function comment\r
650// TODO: wParam - add argument and description to function comment\r
651// TODO: lParam - add argument and description to function comment\r
652LRESULT\r
653CALLBACK\r
654WinNtGopThreadWindowProc (\r
655 IN HWND hwnd,\r
656 IN UINT iMsg,\r
657 IN WPARAM wParam,\r
658 IN LPARAM lParam\r
659 )\r
660{\r
661 GOP_PRIVATE_DATA *Private;\r
662 UINTN Size;\r
663 HDC Handle;\r
664 PAINTSTRUCT PaintStruct;\r
665 LPARAM Index;\r
666 EFI_INPUT_KEY Key;\r
df7499fc 667 BOOLEAN AltIsPress;\r
c9fc89a3 668\r
669 //\r
670 // BugBug - if there are two instances of this DLL in memory (such as is\r
671 // the case for ERM), the correct instance of this function may not be called.\r
672 // This also means that the address of the mTlsIndex value will be wrong, and\r
673 // the value may be wrong too.\r
674 //\r
675\r
676\r
677 //\r
678 // Use mTlsIndex global to get a Thread Local Storage version of Private.\r
679 // This works since each Gop protocol has a unique Private data instance and\r
680 // a unique thread.\r
681 //\r
df7499fc 682 AltIsPress = FALSE;\r
c9fc89a3 683 Private = mWinNt->TlsGetValue (mTlsIndex);\r
684 ASSERT (NULL != Private);\r
685\r
686 switch (iMsg) {\r
687 case WM_CREATE:\r
688 Size = Private->GraphicsOutput.Mode->Info->HorizontalResolution * Private->GraphicsOutput.Mode->Info->VerticalResolution * sizeof (RGBQUAD);\r
689\r
690 //\r
691 // Allocate DIB frame buffer directly from NT for performance enhancement\r
692 // This buffer is the virtual screen/frame buffer. This buffer is not the\r
693 // same a a frame buffer. The first fow of this buffer will be the bottom\r
694 // line of the image. This is an artifact of the way we draw to the screen.\r
695 //\r
696 Private->VirtualScreenInfo = Private->WinNtThunk->HeapAlloc (\r
697 Private->WinNtThunk->GetProcessHeap (),\r
698 HEAP_ZERO_MEMORY,\r
699 Size\r
700 );\r
701\r
702 Private->VirtualScreenInfo->bV4Size = sizeof (BITMAPV4HEADER);\r
703 Private->VirtualScreenInfo->bV4Width = Private->GraphicsOutput.Mode->Info->HorizontalResolution;\r
704 Private->VirtualScreenInfo->bV4Height = Private->GraphicsOutput.Mode->Info->VerticalResolution;\r
705 Private->VirtualScreenInfo->bV4Planes = 1;\r
706 Private->VirtualScreenInfo->bV4BitCount = 32;\r
707 //\r
708 // uncompressed\r
709 //\r
710 Private->VirtualScreenInfo->bV4V4Compression = BI_RGB;\r
711 Private->VirtualScreen = (RGBQUAD *) (Private->VirtualScreenInfo + 1);\r
712 return 0;\r
713\r
714 case WM_PAINT:\r
715 //\r
716 // I have not found a way to convert hwnd into a Private context. So for\r
717 // now we use this API to convert hwnd to Private data.\r
718 //\r
719\r
720 Handle = mWinNt->BeginPaint (hwnd, &PaintStruct);\r
721\r
722 mWinNt->SetDIBitsToDevice (\r
723 Handle, // Destination Device Context\r
724 0, // Destination X - 0\r
725 0, // Destination Y - 0\r
726 Private->GraphicsOutput.Mode->Info->HorizontalResolution, // Width\r
727 Private->GraphicsOutput.Mode->Info->VerticalResolution, // Height\r
728 0, // Source X\r
729 0, // Source Y\r
730 0, // DIB Start Scan Line\r
731 Private->GraphicsOutput.Mode->Info->VerticalResolution, // Number of scan lines\r
732 Private->VirtualScreen, // Address of array of DIB bits\r
733 (BITMAPINFO *) Private->VirtualScreenInfo, // Address of structure with bitmap info\r
734 DIB_RGB_COLORS // RGB or palette indexes\r
735 );\r
736\r
737 mWinNt->EndPaint (hwnd, &PaintStruct);\r
738 return 0;\r
739\r
740 //\r
741 // F10 and the ALT key do not create a WM_KEYDOWN message, thus this special case\r
df7499fc 742 // WM_SYSKEYDOWN is posted when F10 is pressed or\r
62cf113f 743 // holds down ALT key and then presses another key.\r
c9fc89a3 744 //\r
745 case WM_SYSKEYDOWN:\r
df7499fc 746\r
747 Key.ScanCode = 0;\r
748 Key.UnicodeChar = CHAR_NULL;\r
c9fc89a3 749 switch (wParam) {\r
750 case VK_F10:\r
751 Key.ScanCode = SCAN_F10;\r
df7499fc 752 Key.UnicodeChar = CHAR_NULL;\r
66fe7146 753 GopPrivateAddKey (Private, Key);\r
c9fc89a3 754 return 0;\r
755 }\r
c9fc89a3 756\r
df7499fc 757 //\r
758 // If ALT or ALT + modifier key is pressed.\r
759 //\r
760 if (WinNtGopConvertParamToEfiKey (Private, &wParam, &lParam, &Key)) {\r
761 if (Key.ScanCode != 0){\r
762 //\r
763 // If ALT is pressed with other ScanCode.\r
764 // Always revers the left Alt for simple.\r
765 //\r
62cf113f 766 Private->LeftAlt = TRUE;\r
767 }\r
66fe7146 768 GopPrivateAddKey (Private, Key);\r
df7499fc 769 //\r
770 // When Alt is released there is no windoes message, so \r
771 // clean it after using it.\r
772 //\r
773 Private->RightAlt = FALSE;\r
774 Private->LeftAlt = FALSE;\r
775 return 0;\r
62cf113f 776 }\r
df7499fc 777 AltIsPress = TRUE;\r
62cf113f 778\r
df7499fc 779 case WM_CHAR: \r
780 //\r
781 // The ESC key also generate WM_CHAR.\r
782 //\r
783 if (wParam == 0x1B) {\r
af1600fd 784 return 0;\r
df7499fc 785 } \r
62cf113f 786\r
df7499fc 787 if (AltIsPress == TRUE) {\r
62cf113f 788 //\r
df7499fc 789 // If AltIsPress is true that means the Alt key is pressed.\r
62cf113f 790 //\r
df7499fc 791 Private->LeftAlt = TRUE;\r
792 }\r
793 for (Index = 0; Index < (lParam & 0xffff); Index++) {\r
794 if (wParam != 0) {\r
795 Key.UnicodeChar = (CHAR16) wParam;\r
796 Key.ScanCode = SCAN_NULL; \r
797 GopPrivateAddKey (Private, Key); \r
798 }\r
799 }\r
800 if (AltIsPress == TRUE) {\r
62cf113f 801 //\r
df7499fc 802 // When Alt is released there is no windoes message, so \r
803 // clean it after using it.\r
62cf113f 804 //\r
df7499fc 805 Private->LeftAlt = FALSE;\r
62cf113f 806 Private->RightAlt = FALSE;\r
c9fc89a3 807 }\r
62cf113f 808 return 0;\r
809\r
df7499fc 810 case WM_SYSKEYUP:\r
811 //\r
812 // ALT is pressed with another key released\r
813 //\r
814 WinNtGopConvertParamToEfiKeyShiftState (Private, &wParam, &lParam, FALSE);\r
62cf113f 815 return 0;\r
816\r
df7499fc 817 case WM_KEYDOWN:\r
af1600fd 818 Key.ScanCode = SCAN_NULL;\r
819 Key.UnicodeChar = CHAR_NULL;\r
c9fc89a3 820 //\r
df7499fc 821 // A value key press will cause a WM_KEYDOWN first, then cause a WM_CHAR\r
822 // So if there is no modifier key updated, skip the WM_KEYDOWN even.\r
c9fc89a3 823 //\r
df7499fc 824 if (WinNtGopConvertParamToEfiKey (Private, &wParam, &lParam, &Key)) {\r
df7499fc 825 //\r
826 // Support the partial keystroke, add all keydown event into the queue.\r
827 //\r
828 GopPrivateAddKey (Private, Key);\r
c9fc89a3 829 }\r
df7499fc 830 return 0;\r
c9fc89a3 831\r
df7499fc 832 case WM_KEYUP:\r
833 WinNtGopConvertParamToEfiKeyShiftState (Private, &wParam, &lParam, FALSE);\r
c9fc89a3 834 return 0;\r
835\r
836 case WM_CLOSE:\r
837 //\r
838 // This close message is issued by user, core is not aware of this,\r
839 // so don't release the window display resource, just hide the window.\r
840 //\r
841 Private->WinNtThunk->ShowWindow (Private->WindowHandle, SW_HIDE);\r
842 return 0;\r
843\r
844 case WM_DESTROY:\r
845 mWinNt->DestroyWindow (hwnd);\r
846 mWinNt->PostQuitMessage (0);\r
847\r
848 mWinNt->HeapFree (Private->WinNtThunk->GetProcessHeap (), 0, Private->VirtualScreenInfo);\r
849\r
850 mWinNt->ExitThread (0);\r
851 return 0;\r
852\r
853 default:\r
854 break;\r
855 };\r
856\r
857 return mWinNt->DefWindowProc (hwnd, iMsg, wParam, lParam);\r
858}\r
859\r
860\r
861/**\r
862 This thread simulates the end of WinMain () aplication. Each Winow nededs\r
863 to process it's events. The messages are dispatched to\r
864 WinNtGopThreadWindowProc ().\r
865 Be very careful sine WinNtGopThreadWinMain () and WinNtGopThreadWindowProc ()\r
866 are running in a seperate thread. We have to do this to process the events.\r
867\r
868 @param lpParameter Handle of window to manage.\r
869\r
870 @return if a WM_QUIT message is returned exit.\r
871\r
872**/\r
873DWORD\r
874WINAPI\r
875WinNtGopThreadWinMain (\r
876 LPVOID lpParameter\r
877 )\r
878{\r
879 MSG Message;\r
880 GOP_PRIVATE_DATA *Private;\r
c9fc89a3 881 RECT Rect;\r
882\r
883 Private = (GOP_PRIVATE_DATA *) lpParameter;\r
884 ASSERT (NULL != Private);\r
885\r
886 //\r
887 // Since each thread has unique private data, save the private data in Thread\r
888 // Local Storage slot. Then the shared global mTlsIndex can be used to get\r
889 // thread specific context.\r
890 //\r
891 Private->WinNtThunk->TlsSetValue (mTlsIndex, Private);\r
892\r
893 Private->ThreadId = Private->WinNtThunk->GetCurrentThreadId ();\r
894\r
895 Private->WindowsClass.cbSize = sizeof (WNDCLASSEX);\r
896 Private->WindowsClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;\r
897 Private->WindowsClass.lpfnWndProc = WinNtGopThreadWindowProc;\r
898 Private->WindowsClass.cbClsExtra = 0;\r
899 Private->WindowsClass.cbWndExtra = 0;\r
900 Private->WindowsClass.hInstance = NULL;\r
901 Private->WindowsClass.hIcon = Private->WinNtThunk->LoadIcon (NULL, IDI_APPLICATION);\r
902 Private->WindowsClass.hCursor = Private->WinNtThunk->LoadCursor (NULL, IDC_ARROW);\r
f66a43b2 903 Private->WindowsClass.hbrBackground = (HBRUSH)(UINTN)COLOR_WINDOW;\r
c9fc89a3 904 Private->WindowsClass.lpszMenuName = NULL;\r
905 Private->WindowsClass.lpszClassName = WIN_NT_GOP_CLASS_NAME;\r
906 Private->WindowsClass.hIconSm = Private->WinNtThunk->LoadIcon (NULL, IDI_APPLICATION);\r
907\r
908 //\r
909 // This call will fail after the first time, but thats O.K. since we only need\r
910 // WIN_NT_GOP_CLASS_NAME to exist to create the window.\r
911 //\r
912 // Note: Multiple instances of this DLL will use the same instance of this\r
913 // Class, including the callback function, unless the Class is unregistered and\r
914 // successfully registered again.\r
915 //\r
a00ec39b 916 Private->WinNtThunk->RegisterClassEx (&Private->WindowsClass);\r
c9fc89a3 917\r
918 //\r
919 // Setting Rect values to allow for the AdjustWindowRect to provide\r
920 // us the correct sizes for the client area when doing the CreateWindowEx\r
921 //\r
922 Rect.top = 0;\r
923 Rect.bottom = Private->GraphicsOutput.Mode->Info->VerticalResolution;\r
924 Rect.left = 0;\r
925 Rect.right = Private->GraphicsOutput.Mode->Info->HorizontalResolution;\r
926\r
927 Private->WinNtThunk->AdjustWindowRect (&Rect, WS_OVERLAPPEDWINDOW, 0);\r
928\r
929 Private->WindowHandle = Private->WinNtThunk->CreateWindowEx (\r
930 0,\r
931 WIN_NT_GOP_CLASS_NAME,\r
932 Private->WindowName,\r
933 WS_OVERLAPPEDWINDOW,\r
934 CW_USEDEFAULT,\r
935 CW_USEDEFAULT,\r
936 Rect.right - Rect.left,\r
937 Rect.bottom - Rect.top,\r
938 NULL,\r
939 NULL,\r
940 NULL,\r
a00ec39b 941 (VOID **)&Private\r
c9fc89a3 942 );\r
943\r
944 //\r
945 // The reset of this thread is the standard winows program. We need a sperate\r
946 // thread since we must process the message loop to make windows act like\r
947 // windows.\r
948 //\r
949\r
950 Private->WinNtThunk->ShowWindow (Private->WindowHandle, SW_SHOW);\r
951 Private->WinNtThunk->UpdateWindow (Private->WindowHandle);\r
952\r
953 //\r
954 // Let the main thread get some work done\r
955 //\r
956 Private->WinNtThunk->ReleaseSemaphore (Private->ThreadInited, 1, NULL);\r
957\r
958 //\r
959 // This is the message loop that all Windows programs need.\r
960 //\r
961 while (Private->WinNtThunk->GetMessage (&Message, Private->WindowHandle, 0, 0)) {\r
962 Private->WinNtThunk->TranslateMessage (&Message);\r
963 Private->WinNtThunk->DispatchMessage (&Message);\r
964 }\r
965\r
f66a43b2 966 return (DWORD)Message.wParam;\r
c9fc89a3 967}\r
968\r
969\r
970/**\r
971 TODO: Add function description\r
972\r
973 @param Private TODO: add argument description\r
974 @param HorizontalResolution TODO: add argument description\r
975 @param VerticalResolution TODO: add argument description\r
976 @param ColorDepth TODO: add argument description\r
977 @param RefreshRate TODO: add argument description\r
978\r
979 @return TODO: add return values\r
980\r
981**/\r
982EFI_STATUS\r
983WinNtGopStartWindow (\r
984 IN GOP_PRIVATE_DATA *Private,\r
985 IN UINT32 HorizontalResolution,\r
986 IN UINT32 VerticalResolution,\r
987 IN UINT32 ColorDepth,\r
988 IN UINT32 RefreshRate\r
989 )\r
990{\r
991 EFI_STATUS Status;\r
992 DWORD NewThreadId;\r
993\r
994 mWinNt = Private->WinNtThunk;\r
995\r
996 //\r
997 // Initialize a Thread Local Storge variable slot. We use TLS to get the\r
998 // correct Private data instance into the windows thread.\r
999 //\r
1000 if (mTlsIndex == TLS_OUT_OF_INDEXES) {\r
1001 ASSERT (0 == mTlsIndexUseCount);\r
1002 mTlsIndex = Private->WinNtThunk->TlsAlloc ();\r
1003 }\r
1004\r
1005 //\r
1006 // always increase the use count!\r
1007 //\r
1008 mTlsIndexUseCount++;\r
1009\r
1010 //\r
1011 // Register to be notified on exit boot services so we can destroy the window.\r
1012 //\r
ae66d8de 1013 Status = gBS->CreateEventEx (\r
1014 EVT_NOTIFY_SIGNAL,\r
c9fc89a3 1015 TPL_CALLBACK,\r
1016 KillNtGopThread,\r
1017 Private,\r
ae66d8de 1018 &gEfiEventExitBootServicesGuid,\r
c9fc89a3 1019 &mGopScreenExitBootServicesEvent\r
1020 );\r
1021\r
1022 Private->ThreadInited = Private->WinNtThunk->CreateSemaphore (NULL, 0, 1, NULL);\r
1023 Private->ThreadHandle = Private->WinNtThunk->CreateThread (\r
1024 NULL,\r
1025 0,\r
1026 WinNtGopThreadWinMain,\r
1027 (VOID *) Private,\r
1028 0,\r
1029 &NewThreadId\r
1030 );\r
1031\r
1032 //\r
1033 // The other thread has entered the windows message loop so we can\r
1034 // continue our initialization.\r
1035 //\r
1036 Private->WinNtThunk->WaitForSingleObject (Private->ThreadInited, INFINITE);\r
1037 Private->WinNtThunk->CloseHandle (Private->ThreadInited);\r
1038\r
1039 return Status;\r
1040}\r
1041\r
1042\r
1043/**\r
1044\r
1045\r
1046 @return None\r
1047\r
1048**/\r
1049// TODO: Private - add argument and description to function comment\r
1050// TODO: EFI_SUCCESS - add return value to function comment\r
1051EFI_STATUS\r
1052WinNtGopConstructor (\r
1053 GOP_PRIVATE_DATA *Private\r
1054 )\r
1055{\r
1056 Private->ModeData = mGopModeData;\r
1057\r
1058 Private->GraphicsOutput.QueryMode = WinNtGopQuerytMode;\r
1059 Private->GraphicsOutput.SetMode = WinNtGopSetMode;\r
1060 Private->GraphicsOutput.Blt = WinNtGopBlt;\r
1061\r
1062 //\r
1063 // Allocate buffer for Graphics Output Protocol mode information\r
1064 //\r
1065 Private->GraphicsOutput.Mode = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE));\r
1066 if (Private->GraphicsOutput.Mode == NULL) {\r
1067 return EFI_OUT_OF_RESOURCES;\r
1068 }\r
1069 Private->GraphicsOutput.Mode->Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
1070 if (Private->GraphicsOutput.Mode->Info == NULL) {\r
1071 return EFI_OUT_OF_RESOURCES;\r
1072 }\r
1073\r
1074 Private->GraphicsOutput.Mode->MaxMode = sizeof(mGopModeData) / sizeof(GOP_MODE_DATA);\r
1075 //\r
1076 // Till now, we have no idea about the window size.\r
1077 //\r
1078 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
1079 Private->GraphicsOutput.Mode->Info->Version = 0;\r
1080 Private->GraphicsOutput.Mode->Info->HorizontalResolution = 0;\r
1081 Private->GraphicsOutput.Mode->Info->VerticalResolution = 0;\r
1082 Private->GraphicsOutput.Mode->Info->PixelFormat = PixelBltOnly;\r
1083 Private->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
1be0dda6 1084 Private->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;\r
c9fc89a3 1085 Private->GraphicsOutput.Mode->FrameBufferSize = 0;\r
1086\r
1087 Private->HardwareNeedsStarting = TRUE;\r
1088 Private->FillLine = NULL;\r
1089\r
1090 WinNtGopInitializeSimpleTextInForWindow (Private);\r
1091\r
1092 return EFI_SUCCESS;\r
1093}\r
1094\r
1095\r
1096/**\r
1097\r
1098\r
1099 @return None\r
1100\r
1101**/\r
1102// TODO: Private - add argument and description to function comment\r
1103// TODO: EFI_SUCCESS - add return value to function comment\r
1104EFI_STATUS\r
1105WinNtGopDestructor (\r
1106 GOP_PRIVATE_DATA *Private\r
1107 )\r
1108{\r
c9fc89a3 1109 if (!Private->HardwareNeedsStarting) {\r
1110 //\r
1111 // BugBug: Shutdown GOP Hardware and any child devices.\r
1112 //\r
1113 Private->WinNtThunk->SendMessage (Private->WindowHandle, WM_DESTROY, 0, 0);\r
1114 Private->WinNtThunk->CloseHandle (Private->ThreadHandle);\r
1115\r
1116 mTlsIndexUseCount--;\r
1117\r
1118 //\r
1119 // The callback function for another window could still be called,\r
1120 // so we need to make sure there are no more users of mTlsIndex.\r
1121 //\r
1122 if (0 == mTlsIndexUseCount) {\r
1123 ASSERT (TLS_OUT_OF_INDEXES != mTlsIndex);\r
1124\r
1125 Private->WinNtThunk->TlsFree (mTlsIndex);\r
1126 mTlsIndex = TLS_OUT_OF_INDEXES;\r
1127\r
a00ec39b 1128 Private->WinNtThunk->UnregisterClass (\r
1129 Private->WindowsClass.lpszClassName,\r
1130 Private->WindowsClass.hInstance\r
1131 );\r
c9fc89a3 1132 }\r
1133\r
1134 WinNtGopDestroySimpleTextInForWindow (Private);\r
1135 }\r
1136\r
1137 //\r
1138 // Free graphics output protocol occupied resource\r
1139 //\r
1140 if (Private->GraphicsOutput.Mode != NULL) {\r
1141 if (Private->GraphicsOutput.Mode->Info != NULL) {\r
1142 FreePool (Private->GraphicsOutput.Mode->Info);\r
1143 }\r
1144 FreePool (Private->GraphicsOutput.Mode);\r
1145 }\r
1146\r
1147 return EFI_SUCCESS;\r
1148}\r
1149\r
1150\r
1151/**\r
1152 This is the GOP screen's callback notification function for exit-boot-services.\r
1153 All we do here is call WinNtGopDestructor().\r
1154\r
1155 @param Event not used\r
1156 @param Context pointer to the Private structure.\r
1157\r
1158 @return None.\r
1159\r
1160**/\r
c9fc89a3 1161VOID\r
1162EFIAPI\r
1163KillNtGopThread (\r
1164 IN EFI_EVENT Event,\r
1165 IN VOID *Context\r
1166 )\r
1167{\r
a00ec39b 1168 WinNtGopDestructor (Context);\r
c9fc89a3 1169}\r