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