]> git.proxmox.com Git - mirror_edk2.git/blame - Nt32Pkg/WinNtGopDxe/WinNtGopScreen.c
Adopt new IPv4/IPv6 device path for network modules.
[mirror_edk2.git] / Nt32Pkg / WinNtGopDxe / WinNtGopScreen.c
CommitLineData
c9fc89a3 1/** @file\r
2\r
66fe7146 3Copyright (c) 2006 - 2011, 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
382 Private->WinNtThunk->MoveWindow (Private->WindowHandle, Rect.left, Rect.top, Width, Height, TRUE);\r
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
585 Rect.left = DestinationX;\r
586 Rect.top = DestinationY;\r
587 Rect.right = DestinationX + Width;\r
588 Rect.bottom = DestinationY + Height;\r
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
784 return 0;\r
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
818 Key.ScanCode = SCAN_NULL;\r
c9fc89a3 819 //\r
df7499fc 820 // A value key press will cause a WM_KEYDOWN first, then cause a WM_CHAR\r
821 // So if there is no modifier key updated, skip the WM_KEYDOWN even.\r
c9fc89a3 822 //\r
df7499fc 823 if (WinNtGopConvertParamToEfiKey (Private, &wParam, &lParam, &Key)) {\r
824 if (Key.ScanCode != SCAN_NULL) {\r
825 Key.UnicodeChar = CHAR_NULL;\r
c9fc89a3 826 }\r
df7499fc 827 //\r
828 // Support the partial keystroke, add all keydown event into the queue.\r
829 //\r
830 GopPrivateAddKey (Private, Key);\r
c9fc89a3 831 }\r
df7499fc 832 return 0;\r
c9fc89a3 833\r
df7499fc 834 case WM_KEYUP:\r
835 WinNtGopConvertParamToEfiKeyShiftState (Private, &wParam, &lParam, FALSE);\r
c9fc89a3 836 return 0;\r
837\r
838 case WM_CLOSE:\r
839 //\r
840 // This close message is issued by user, core is not aware of this,\r
841 // so don't release the window display resource, just hide the window.\r
842 //\r
843 Private->WinNtThunk->ShowWindow (Private->WindowHandle, SW_HIDE);\r
844 return 0;\r
845\r
846 case WM_DESTROY:\r
847 mWinNt->DestroyWindow (hwnd);\r
848 mWinNt->PostQuitMessage (0);\r
849\r
850 mWinNt->HeapFree (Private->WinNtThunk->GetProcessHeap (), 0, Private->VirtualScreenInfo);\r
851\r
852 mWinNt->ExitThread (0);\r
853 return 0;\r
854\r
855 default:\r
856 break;\r
857 };\r
858\r
859 return mWinNt->DefWindowProc (hwnd, iMsg, wParam, lParam);\r
860}\r
861\r
862\r
863/**\r
864 This thread simulates the end of WinMain () aplication. Each Winow nededs\r
865 to process it's events. The messages are dispatched to\r
866 WinNtGopThreadWindowProc ().\r
867 Be very careful sine WinNtGopThreadWinMain () and WinNtGopThreadWindowProc ()\r
868 are running in a seperate thread. We have to do this to process the events.\r
869\r
870 @param lpParameter Handle of window to manage.\r
871\r
872 @return if a WM_QUIT message is returned exit.\r
873\r
874**/\r
875DWORD\r
876WINAPI\r
877WinNtGopThreadWinMain (\r
878 LPVOID lpParameter\r
879 )\r
880{\r
881 MSG Message;\r
882 GOP_PRIVATE_DATA *Private;\r
c9fc89a3 883 RECT Rect;\r
884\r
885 Private = (GOP_PRIVATE_DATA *) lpParameter;\r
886 ASSERT (NULL != Private);\r
887\r
888 //\r
889 // Since each thread has unique private data, save the private data in Thread\r
890 // Local Storage slot. Then the shared global mTlsIndex can be used to get\r
891 // thread specific context.\r
892 //\r
893 Private->WinNtThunk->TlsSetValue (mTlsIndex, Private);\r
894\r
895 Private->ThreadId = Private->WinNtThunk->GetCurrentThreadId ();\r
896\r
897 Private->WindowsClass.cbSize = sizeof (WNDCLASSEX);\r
898 Private->WindowsClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;\r
899 Private->WindowsClass.lpfnWndProc = WinNtGopThreadWindowProc;\r
900 Private->WindowsClass.cbClsExtra = 0;\r
901 Private->WindowsClass.cbWndExtra = 0;\r
902 Private->WindowsClass.hInstance = NULL;\r
903 Private->WindowsClass.hIcon = Private->WinNtThunk->LoadIcon (NULL, IDI_APPLICATION);\r
904 Private->WindowsClass.hCursor = Private->WinNtThunk->LoadCursor (NULL, IDC_ARROW);\r
905 Private->WindowsClass.hbrBackground = (HBRUSH) COLOR_WINDOW;\r
906 Private->WindowsClass.lpszMenuName = NULL;\r
907 Private->WindowsClass.lpszClassName = WIN_NT_GOP_CLASS_NAME;\r
908 Private->WindowsClass.hIconSm = Private->WinNtThunk->LoadIcon (NULL, IDI_APPLICATION);\r
909\r
910 //\r
911 // This call will fail after the first time, but thats O.K. since we only need\r
912 // WIN_NT_GOP_CLASS_NAME to exist to create the window.\r
913 //\r
914 // Note: Multiple instances of this DLL will use the same instance of this\r
915 // Class, including the callback function, unless the Class is unregistered and\r
916 // successfully registered again.\r
917 //\r
a00ec39b 918 Private->WinNtThunk->RegisterClassEx (&Private->WindowsClass);\r
c9fc89a3 919\r
920 //\r
921 // Setting Rect values to allow for the AdjustWindowRect to provide\r
922 // us the correct sizes for the client area when doing the CreateWindowEx\r
923 //\r
924 Rect.top = 0;\r
925 Rect.bottom = Private->GraphicsOutput.Mode->Info->VerticalResolution;\r
926 Rect.left = 0;\r
927 Rect.right = Private->GraphicsOutput.Mode->Info->HorizontalResolution;\r
928\r
929 Private->WinNtThunk->AdjustWindowRect (&Rect, WS_OVERLAPPEDWINDOW, 0);\r
930\r
931 Private->WindowHandle = Private->WinNtThunk->CreateWindowEx (\r
932 0,\r
933 WIN_NT_GOP_CLASS_NAME,\r
934 Private->WindowName,\r
935 WS_OVERLAPPEDWINDOW,\r
936 CW_USEDEFAULT,\r
937 CW_USEDEFAULT,\r
938 Rect.right - Rect.left,\r
939 Rect.bottom - Rect.top,\r
940 NULL,\r
941 NULL,\r
942 NULL,\r
a00ec39b 943 (VOID **)&Private\r
c9fc89a3 944 );\r
945\r
946 //\r
947 // The reset of this thread is the standard winows program. We need a sperate\r
948 // thread since we must process the message loop to make windows act like\r
949 // windows.\r
950 //\r
951\r
952 Private->WinNtThunk->ShowWindow (Private->WindowHandle, SW_SHOW);\r
953 Private->WinNtThunk->UpdateWindow (Private->WindowHandle);\r
954\r
955 //\r
956 // Let the main thread get some work done\r
957 //\r
958 Private->WinNtThunk->ReleaseSemaphore (Private->ThreadInited, 1, NULL);\r
959\r
960 //\r
961 // This is the message loop that all Windows programs need.\r
962 //\r
963 while (Private->WinNtThunk->GetMessage (&Message, Private->WindowHandle, 0, 0)) {\r
964 Private->WinNtThunk->TranslateMessage (&Message);\r
965 Private->WinNtThunk->DispatchMessage (&Message);\r
966 }\r
967\r
968 return Message.wParam;\r
969}\r
970\r
971\r
972/**\r
973 TODO: Add function description\r
974\r
975 @param Private TODO: add argument description\r
976 @param HorizontalResolution TODO: add argument description\r
977 @param VerticalResolution TODO: add argument description\r
978 @param ColorDepth TODO: add argument description\r
979 @param RefreshRate TODO: add argument description\r
980\r
981 @return TODO: add return values\r
982\r
983**/\r
984EFI_STATUS\r
985WinNtGopStartWindow (\r
986 IN GOP_PRIVATE_DATA *Private,\r
987 IN UINT32 HorizontalResolution,\r
988 IN UINT32 VerticalResolution,\r
989 IN UINT32 ColorDepth,\r
990 IN UINT32 RefreshRate\r
991 )\r
992{\r
993 EFI_STATUS Status;\r
994 DWORD NewThreadId;\r
995\r
996 mWinNt = Private->WinNtThunk;\r
997\r
998 //\r
999 // Initialize a Thread Local Storge variable slot. We use TLS to get the\r
1000 // correct Private data instance into the windows thread.\r
1001 //\r
1002 if (mTlsIndex == TLS_OUT_OF_INDEXES) {\r
1003 ASSERT (0 == mTlsIndexUseCount);\r
1004 mTlsIndex = Private->WinNtThunk->TlsAlloc ();\r
1005 }\r
1006\r
1007 //\r
1008 // always increase the use count!\r
1009 //\r
1010 mTlsIndexUseCount++;\r
1011\r
1012 //\r
1013 // Register to be notified on exit boot services so we can destroy the window.\r
1014 //\r
ae66d8de 1015 Status = gBS->CreateEventEx (\r
1016 EVT_NOTIFY_SIGNAL,\r
c9fc89a3 1017 TPL_CALLBACK,\r
1018 KillNtGopThread,\r
1019 Private,\r
ae66d8de 1020 &gEfiEventExitBootServicesGuid,\r
c9fc89a3 1021 &mGopScreenExitBootServicesEvent\r
1022 );\r
1023\r
1024 Private->ThreadInited = Private->WinNtThunk->CreateSemaphore (NULL, 0, 1, NULL);\r
1025 Private->ThreadHandle = Private->WinNtThunk->CreateThread (\r
1026 NULL,\r
1027 0,\r
1028 WinNtGopThreadWinMain,\r
1029 (VOID *) Private,\r
1030 0,\r
1031 &NewThreadId\r
1032 );\r
1033\r
1034 //\r
1035 // The other thread has entered the windows message loop so we can\r
1036 // continue our initialization.\r
1037 //\r
1038 Private->WinNtThunk->WaitForSingleObject (Private->ThreadInited, INFINITE);\r
1039 Private->WinNtThunk->CloseHandle (Private->ThreadInited);\r
1040\r
1041 return Status;\r
1042}\r
1043\r
1044\r
1045/**\r
1046\r
1047\r
1048 @return None\r
1049\r
1050**/\r
1051// TODO: Private - add argument and description to function comment\r
1052// TODO: EFI_SUCCESS - add return value to function comment\r
1053EFI_STATUS\r
1054WinNtGopConstructor (\r
1055 GOP_PRIVATE_DATA *Private\r
1056 )\r
1057{\r
1058 Private->ModeData = mGopModeData;\r
1059\r
1060 Private->GraphicsOutput.QueryMode = WinNtGopQuerytMode;\r
1061 Private->GraphicsOutput.SetMode = WinNtGopSetMode;\r
1062 Private->GraphicsOutput.Blt = WinNtGopBlt;\r
1063\r
1064 //\r
1065 // Allocate buffer for Graphics Output Protocol mode information\r
1066 //\r
1067 Private->GraphicsOutput.Mode = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE));\r
1068 if (Private->GraphicsOutput.Mode == NULL) {\r
1069 return EFI_OUT_OF_RESOURCES;\r
1070 }\r
1071 Private->GraphicsOutput.Mode->Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
1072 if (Private->GraphicsOutput.Mode->Info == NULL) {\r
1073 return EFI_OUT_OF_RESOURCES;\r
1074 }\r
1075\r
1076 Private->GraphicsOutput.Mode->MaxMode = sizeof(mGopModeData) / sizeof(GOP_MODE_DATA);\r
1077 //\r
1078 // Till now, we have no idea about the window size.\r
1079 //\r
1080 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
1081 Private->GraphicsOutput.Mode->Info->Version = 0;\r
1082 Private->GraphicsOutput.Mode->Info->HorizontalResolution = 0;\r
1083 Private->GraphicsOutput.Mode->Info->VerticalResolution = 0;\r
1084 Private->GraphicsOutput.Mode->Info->PixelFormat = PixelBltOnly;\r
1085 Private->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
1be0dda6 1086 Private->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;\r
c9fc89a3 1087 Private->GraphicsOutput.Mode->FrameBufferSize = 0;\r
1088\r
1089 Private->HardwareNeedsStarting = TRUE;\r
1090 Private->FillLine = NULL;\r
1091\r
1092 WinNtGopInitializeSimpleTextInForWindow (Private);\r
1093\r
1094 return EFI_SUCCESS;\r
1095}\r
1096\r
1097\r
1098/**\r
1099\r
1100\r
1101 @return None\r
1102\r
1103**/\r
1104// TODO: Private - add argument and description to function comment\r
1105// TODO: EFI_SUCCESS - add return value to function comment\r
1106EFI_STATUS\r
1107WinNtGopDestructor (\r
1108 GOP_PRIVATE_DATA *Private\r
1109 )\r
1110{\r
c9fc89a3 1111 if (!Private->HardwareNeedsStarting) {\r
1112 //\r
1113 // BugBug: Shutdown GOP Hardware and any child devices.\r
1114 //\r
1115 Private->WinNtThunk->SendMessage (Private->WindowHandle, WM_DESTROY, 0, 0);\r
1116 Private->WinNtThunk->CloseHandle (Private->ThreadHandle);\r
1117\r
1118 mTlsIndexUseCount--;\r
1119\r
1120 //\r
1121 // The callback function for another window could still be called,\r
1122 // so we need to make sure there are no more users of mTlsIndex.\r
1123 //\r
1124 if (0 == mTlsIndexUseCount) {\r
1125 ASSERT (TLS_OUT_OF_INDEXES != mTlsIndex);\r
1126\r
1127 Private->WinNtThunk->TlsFree (mTlsIndex);\r
1128 mTlsIndex = TLS_OUT_OF_INDEXES;\r
1129\r
a00ec39b 1130 Private->WinNtThunk->UnregisterClass (\r
1131 Private->WindowsClass.lpszClassName,\r
1132 Private->WindowsClass.hInstance\r
1133 );\r
c9fc89a3 1134 }\r
1135\r
1136 WinNtGopDestroySimpleTextInForWindow (Private);\r
1137 }\r
1138\r
1139 //\r
1140 // Free graphics output protocol occupied resource\r
1141 //\r
1142 if (Private->GraphicsOutput.Mode != NULL) {\r
1143 if (Private->GraphicsOutput.Mode->Info != NULL) {\r
1144 FreePool (Private->GraphicsOutput.Mode->Info);\r
1145 }\r
1146 FreePool (Private->GraphicsOutput.Mode);\r
1147 }\r
1148\r
1149 return EFI_SUCCESS;\r
1150}\r
1151\r
1152\r
1153/**\r
1154 This is the GOP screen's callback notification function for exit-boot-services.\r
1155 All we do here is call WinNtGopDestructor().\r
1156\r
1157 @param Event not used\r
1158 @param Context pointer to the Private structure.\r
1159\r
1160 @return None.\r
1161\r
1162**/\r
c9fc89a3 1163VOID\r
1164EFIAPI\r
1165KillNtGopThread (\r
1166 IN EFI_EVENT Event,\r
1167 IN VOID *Context\r
1168 )\r
1169{\r
a00ec39b 1170 WinNtGopDestructor (Context);\r
c9fc89a3 1171}\r