mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-11-03 21:17:23 +01:00 
			
		
		
		
	git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8616 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1113 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1113 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
 | 
						|
Copyright (c) 2006 - 2009, Intel Corporation
 | 
						|
All rights reserved. This program and the accompanying materials
 | 
						|
are licensed and made available under the terms and conditions of the BSD License
 | 
						|
which accompanies this distribution.  The full text of the license may be found at
 | 
						|
http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
Module Name:
 | 
						|
 | 
						|
    WinNtGopScreen.c
 | 
						|
 | 
						|
Abstract:
 | 
						|
 | 
						|
  This file produces the graphics abstration of GOP. It is called by
 | 
						|
  WinNtGopDriver.c file which deals with the UEFI 2.0 driver model.
 | 
						|
  This file just does graphics.
 | 
						|
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "WinNtGop.h"
 | 
						|
 | 
						|
EFI_WIN_NT_THUNK_PROTOCOL *mWinNt;
 | 
						|
DWORD                     mTlsIndex         = TLS_OUT_OF_INDEXES;
 | 
						|
DWORD                     mTlsIndexUseCount = 0;  // lets us know when we can free mTlsIndex.
 | 
						|
EFI_EVENT          mGopScreenExitBootServicesEvent;
 | 
						|
GOP_MODE_DATA mGopModeData[] = {
 | 
						|
    {800, 600, 0, 0},
 | 
						|
    {640, 480, 0, 0},
 | 
						|
    {720, 400, 0, 0},
 | 
						|
    {1024, 768, 0, 0},
 | 
						|
    {1280, 1024, 0, 0}
 | 
						|
    };
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
WinNtGopStartWindow (
 | 
						|
  IN  GOP_PRIVATE_DATA    *Private,
 | 
						|
  IN  UINT32              HorizontalResolution,
 | 
						|
  IN  UINT32              VerticalResolution,
 | 
						|
  IN  UINT32              ColorDepth,
 | 
						|
  IN  UINT32              RefreshRate
 | 
						|
  );
 | 
						|
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
KillNtGopThread (
 | 
						|
  IN EFI_EVENT  Event,
 | 
						|
  IN VOID       *Context
 | 
						|
  );
 | 
						|
 | 
						|
VOID
 | 
						|
WinNtGopConvertParamToEfiKeyShiftState (
 | 
						|
  IN  GOP_PRIVATE_DATA  *Private,
 | 
						|
  IN  WPARAM            *wParam,
 | 
						|
  IN  BOOLEAN           Flag
 | 
						|
  )
 | 
						|
{
 | 
						|
  switch (*wParam) {
 | 
						|
  //
 | 
						|
  // BUGBUG: Only GetAsyncKeyState() and GetKeyState() can distinguish
 | 
						|
  // left and right Ctrl, and Shift key. 
 | 
						|
  // Neither of the two is defined in EFI_WIN_NT_THUNK_PROTOCOL. 
 | 
						|
  // Therefor, we can not set the correct Shift state here.
 | 
						|
  // 
 | 
						|
  case VK_SHIFT:  
 | 
						|
    Private->LeftShift  = Flag;
 | 
						|
    break;  
 | 
						|
  case VK_CONTROL:
 | 
						|
    Private->LeftCtrl   = Flag;
 | 
						|
    break;
 | 
						|
  case VK_LWIN:      
 | 
						|
    Private->LeftLogo   = Flag;
 | 
						|
    break;
 | 
						|
  case VK_RWIN:      
 | 
						|
    Private->RightLogo  = Flag;
 | 
						|
    break;
 | 
						|
  case VK_APPS:      
 | 
						|
    Private->Menu       = Flag;
 | 
						|
    break;
 | 
						|
  //
 | 
						|
  // BUGBUG: PrintScreen/SysRq can not trigger WM_KEYDOWN message,
 | 
						|
  // so SySReq shift state is not supported here.
 | 
						|
  //
 | 
						|
  case VK_PRINT:  
 | 
						|
    Private->SysReq     = Flag;
 | 
						|
    break;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
WinNtGopConvertParamToEfiKey (
 | 
						|
  IN  GOP_PRIVATE_DATA  *Private,
 | 
						|
  IN  WPARAM            *wParam,
 | 
						|
  IN  EFI_INPUT_KEY     *Key
 | 
						|
  )
 | 
						|
{
 | 
						|
  switch (*wParam) {
 | 
						|
  case VK_HOME:       Key->ScanCode = SCAN_HOME;       break;
 | 
						|
  case VK_END:        Key->ScanCode = SCAN_END;        break;
 | 
						|
  case VK_LEFT:       Key->ScanCode = SCAN_LEFT;       break;
 | 
						|
  case VK_RIGHT:      Key->ScanCode = SCAN_RIGHT;      break;
 | 
						|
  case VK_UP:         Key->ScanCode = SCAN_UP;         break;
 | 
						|
  case VK_DOWN:       Key->ScanCode = SCAN_DOWN;       break;
 | 
						|
  case VK_DELETE:     Key->ScanCode = SCAN_DELETE;     break;
 | 
						|
  case VK_INSERT:     Key->ScanCode = SCAN_INSERT;     break;
 | 
						|
  case VK_PRIOR:      Key->ScanCode = SCAN_PAGE_UP;    break;
 | 
						|
  case VK_NEXT:       Key->ScanCode = SCAN_PAGE_DOWN;  break;
 | 
						|
  case VK_ESCAPE:     Key->ScanCode = SCAN_ESC;        break;
 | 
						|
                         
 | 
						|
  case VK_F1:         Key->ScanCode = SCAN_F1;         break;
 | 
						|
  case VK_F2:         Key->ScanCode = SCAN_F2;         break;
 | 
						|
  case VK_F3:         Key->ScanCode = SCAN_F3;         break;
 | 
						|
  case VK_F4:         Key->ScanCode = SCAN_F4;         break;
 | 
						|
  case VK_F5:         Key->ScanCode = SCAN_F5;         break;
 | 
						|
  case VK_F6:         Key->ScanCode = SCAN_F6;         break;
 | 
						|
  case VK_F7:         Key->ScanCode = SCAN_F7;         break;
 | 
						|
  case VK_F8:         Key->ScanCode = SCAN_F8;         break;
 | 
						|
  case VK_F9:         Key->ScanCode = SCAN_F9;         break;
 | 
						|
  case VK_F11:        Key->ScanCode = SCAN_F11;        break;
 | 
						|
  case VK_F12:        Key->ScanCode = SCAN_F12;        break;
 | 
						|
 | 
						|
  case VK_F13:        Key->ScanCode = SCAN_F13;        break;
 | 
						|
  case VK_F14:        Key->ScanCode = SCAN_F14;        break;
 | 
						|
  case VK_F15:        Key->ScanCode = SCAN_F15;        break;
 | 
						|
  case VK_F16:        Key->ScanCode = SCAN_F16;        break;
 | 
						|
  case VK_F17:        Key->ScanCode = SCAN_F17;        break;
 | 
						|
  case VK_F18:        Key->ScanCode = SCAN_F18;        break;
 | 
						|
  case VK_F19:        Key->ScanCode = SCAN_F19;        break;
 | 
						|
  case VK_F20:        Key->ScanCode = SCAN_F20;        break;
 | 
						|
  case VK_F21:        Key->ScanCode = SCAN_F21;        break;
 | 
						|
  case VK_F22:        Key->ScanCode = SCAN_F22;        break;
 | 
						|
  case VK_F23:        Key->ScanCode = SCAN_F23;        break;
 | 
						|
  case VK_F24:        Key->ScanCode = SCAN_F24;        break;
 | 
						|
 | 
						|
  //
 | 
						|
  // Set toggle state
 | 
						|
  //    
 | 
						|
  case VK_NUMLOCK:     
 | 
						|
    Private->NumLock    = (BOOLEAN)(!Private->NumLock);
 | 
						|
    break;
 | 
						|
  case VK_SCROLL:
 | 
						|
    Private->ScrollLock = (BOOLEAN)(!Private->ScrollLock);
 | 
						|
    break;  
 | 
						|
  case VK_CAPITAL:
 | 
						|
    Private->CapsLock   = (BOOLEAN)(!Private->CapsLock);
 | 
						|
    break;  
 | 
						|
  }
 | 
						|
  
 | 
						|
  WinNtGopConvertParamToEfiKeyShiftState (Private, wParam, TRUE);  
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//
 | 
						|
// GOP Protocol Member Functions
 | 
						|
//
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Graphics Output protocol interface to get video mode
 | 
						|
 | 
						|
  @param  This                   Protocol instance pointer.
 | 
						|
  @param  ModeNumber             The mode number to return information on.
 | 
						|
  @param  Info                   Caller allocated buffer that returns information
 | 
						|
                                 about ModeNumber.
 | 
						|
  @param  SizeOfInfo             A pointer to the size, in bytes, of the Info
 | 
						|
                                 buffer.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Mode information returned.
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL   The Info buffer was too small.
 | 
						|
  @retval EFI_DEVICE_ERROR       A hardware error occurred trying to retrieve the
 | 
						|
                                 video mode.
 | 
						|
  @retval EFI_NOT_STARTED        Video display is not initialized. Call SetMode ()
 | 
						|
  @retval EFI_INVALID_PARAMETER  One of the input args was NULL.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
WinNtGopQuerytMode (
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
 | 
						|
  IN  UINT32                                ModeNumber,
 | 
						|
  OUT UINTN                                 *SizeOfInfo,
 | 
						|
  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
 | 
						|
  )
 | 
						|
{
 | 
						|
  GOP_PRIVATE_DATA  *Private;
 | 
						|
 | 
						|
  Private = GOP_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  if (Info == NULL || SizeOfInfo == NULL || (UINTN) ModeNumber >= This->Mode->MaxMode) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
 | 
						|
  if (*Info == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
 | 
						|
 | 
						|
  (*Info)->Version = 0;
 | 
						|
  (*Info)->HorizontalResolution = Private->ModeData[ModeNumber].HorizontalResolution;
 | 
						|
  (*Info)->VerticalResolution   = Private->ModeData[ModeNumber].VerticalResolution;
 | 
						|
  (*Info)->PixelFormat = PixelBltOnly;
 | 
						|
  (*Info)->PixelsPerScanLine = (*Info)->HorizontalResolution;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Graphics Output protocol interface to set video mode
 | 
						|
 | 
						|
  @param  This                   Protocol instance pointer.
 | 
						|
  @param  ModeNumber             The mode number to be set.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Graphics mode was changed.
 | 
						|
  @retval EFI_DEVICE_ERROR       The device had an error and could not complete the
 | 
						|
                                 request.
 | 
						|
  @retval EFI_UNSUPPORTED        ModeNumber is not supported by this device.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
WinNtGopSetMode (
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
 | 
						|
  IN  UINT32                       ModeNumber
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  GOP_PRIVATE_DATA              *Private;
 | 
						|
  GOP_MODE_DATA *ModeData;
 | 
						|
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill;
 | 
						|
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *NewFillLine;
 | 
						|
  RECT                          Rect;
 | 
						|
  UINTN                         Size;
 | 
						|
  UINTN                         Width;
 | 
						|
  UINTN                         Height;
 | 
						|
 | 
						|
  Private = GOP_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  if (ModeNumber >= This->Mode->MaxMode) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  ModeData = &Private->ModeData[ModeNumber];
 | 
						|
  This->Mode->Mode = ModeNumber;
 | 
						|
  Private->GraphicsOutput.Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
 | 
						|
  Private->GraphicsOutput.Mode->Info->VerticalResolution = ModeData->VerticalResolution;
 | 
						|
  Private->GraphicsOutput.Mode->Info->PixelsPerScanLine = ModeData->HorizontalResolution;
 | 
						|
 | 
						|
  if (Private->HardwareNeedsStarting) {
 | 
						|
    Status = WinNtGopStartWindow (
 | 
						|
              Private,
 | 
						|
              ModeData->HorizontalResolution,
 | 
						|
              ModeData->VerticalResolution,
 | 
						|
              ModeData->ColorDepth,
 | 
						|
              ModeData->RefreshRate
 | 
						|
              );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return EFI_DEVICE_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    Private->HardwareNeedsStarting = FALSE;
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Change the resolution and resize of the window
 | 
						|
    //
 | 
						|
 | 
						|
    //
 | 
						|
    // Free the old buffer. We do not save the content of the old buffer since the
 | 
						|
    // screen is to be cleared anyway. Clearing the screen is required by the EFI spec.
 | 
						|
    // See UEFI spec -EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode()
 | 
						|
    //
 | 
						|
    Private->WinNtThunk->HeapFree (Private->WinNtThunk->GetProcessHeap (), 0, Private->VirtualScreenInfo);
 | 
						|
 | 
						|
    //
 | 
						|
    // Allocate DIB frame buffer directly from NT for performance enhancement
 | 
						|
    // This buffer is the virtual screen/frame buffer. This buffer is not the
 | 
						|
    // same a a frame buffer. The first row of this buffer will be the bottom
 | 
						|
    // line of the image. This is an artifact of the way we draw to the screen.
 | 
						|
    //
 | 
						|
    Size = ModeData->HorizontalResolution * ModeData->VerticalResolution * sizeof (RGBQUAD) + sizeof (BITMAPV4HEADER);
 | 
						|
    Private->VirtualScreenInfo = Private->WinNtThunk->HeapAlloc (
 | 
						|
                                                        Private->WinNtThunk->GetProcessHeap (),
 | 
						|
                                                        HEAP_ZERO_MEMORY,
 | 
						|
                                                        Size
 | 
						|
                                                        );
 | 
						|
 | 
						|
    //
 | 
						|
    // Update the virtual screen info data structure
 | 
						|
    //
 | 
						|
    Private->VirtualScreenInfo->bV4Size           = sizeof (BITMAPV4HEADER);
 | 
						|
    Private->VirtualScreenInfo->bV4Width          = ModeData->HorizontalResolution;
 | 
						|
    Private->VirtualScreenInfo->bV4Height         = ModeData->VerticalResolution;
 | 
						|
    Private->VirtualScreenInfo->bV4Planes         = 1;
 | 
						|
    Private->VirtualScreenInfo->bV4BitCount       = 32;
 | 
						|
    //
 | 
						|
    // uncompressed
 | 
						|
    //
 | 
						|
    Private->VirtualScreenInfo->bV4V4Compression  = BI_RGB;
 | 
						|
 | 
						|
    //
 | 
						|
    // The rest of the allocated memory block is the virtual screen buffer
 | 
						|
    //
 | 
						|
    Private->VirtualScreen = (RGBQUAD *) (Private->VirtualScreenInfo + 1);
 | 
						|
 | 
						|
    //
 | 
						|
    // Use the AdjuctWindowRect fuction to calculate the real width and height
 | 
						|
    // of the new window including the border and caption
 | 
						|
    //
 | 
						|
    Rect.left   = 0;
 | 
						|
    Rect.top    = 0;
 | 
						|
    Rect.right  = ModeData->HorizontalResolution;
 | 
						|
    Rect.bottom = ModeData->VerticalResolution;
 | 
						|
 | 
						|
    Private->WinNtThunk->AdjustWindowRect (&Rect, WS_OVERLAPPEDWINDOW, 0);
 | 
						|
 | 
						|
    Width   = Rect.right - Rect.left;
 | 
						|
    Height  = Rect.bottom - Rect.top;
 | 
						|
 | 
						|
    //
 | 
						|
    // Retrieve the original window position information
 | 
						|
    //
 | 
						|
    Private->WinNtThunk->GetWindowRect (Private->WindowHandle, &Rect);
 | 
						|
 | 
						|
    //
 | 
						|
    // Adjust the window size
 | 
						|
    //
 | 
						|
    Private->WinNtThunk->MoveWindow (Private->WindowHandle, Rect.left, Rect.top, Width, Height, TRUE);
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  NewFillLine = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ModeData->HorizontalResolution);
 | 
						|
  if (NewFillLine == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Private->FillLine != NULL) {
 | 
						|
    FreePool (Private->FillLine);
 | 
						|
  }
 | 
						|
 | 
						|
  Private->FillLine             = NewFillLine;
 | 
						|
 | 
						|
  Fill.Red                      = 0x00;
 | 
						|
  Fill.Green                    = 0x00;
 | 
						|
  Fill.Blue                     = 0x00;
 | 
						|
  This->Blt (
 | 
						|
          This,
 | 
						|
          &Fill,
 | 
						|
          EfiBltVideoFill,
 | 
						|
          0,
 | 
						|
          0,
 | 
						|
          0,
 | 
						|
          0,
 | 
						|
          ModeData->HorizontalResolution,
 | 
						|
          ModeData->VerticalResolution,
 | 
						|
          ModeData->HorizontalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
 | 
						|
          );
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Blt pixels from the rectangle (Width X Height) formed by the BltBuffer
 | 
						|
  onto the graphics screen starting a location (X, Y). (0, 0) is defined as
 | 
						|
  the upper left hand side of the screen. (X, Y) can be outside of the
 | 
						|
  current screen geometry and the BltBuffer will be cliped when it is
 | 
						|
  displayed. X and Y can be negative or positive. If Width or Height is
 | 
						|
  bigger than the current video screen the image will be clipped.
 | 
						|
 | 
						|
  @param  This                   Protocol instance pointer.
 | 
						|
  @param  X                      X location on graphics screen.
 | 
						|
  @param  Y                      Y location on the graphics screen.
 | 
						|
  @param  Width                  Width of BltBuffer.
 | 
						|
  @param  Height                 Hight of BltBuffer
 | 
						|
  @param  BltOperation           Operation to perform on BltBuffer and video memory
 | 
						|
  @param  BltBuffer              Buffer containing data to blt into video buffer.
 | 
						|
                                 This  buffer has a size of
 | 
						|
                                 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
 | 
						|
  @param  SourceX                If the BltOperation is a EfiCopyBlt this is the
 | 
						|
                                 source of the copy. For other BLT operations this
 | 
						|
                                 argument is not used.
 | 
						|
  @param  SourceX                If the BltOperation is a EfiCopyBlt this is the
 | 
						|
                                 source of the copy. For other BLT operations this
 | 
						|
                                 argument is not used.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            The palette is updated with PaletteArray.
 | 
						|
  @retval EFI_INVALID_PARAMETER  BltOperation is not valid.
 | 
						|
  @retval EFI_DEVICE_ERROR       A hardware error occured writting to the video
 | 
						|
                                 buffer.
 | 
						|
 | 
						|
**/
 | 
						|
// TODO:    SourceY - add argument and description to function comment
 | 
						|
// TODO:    DestinationX - add argument and description to function comment
 | 
						|
// TODO:    DestinationY - add argument and description to function comment
 | 
						|
// TODO:    Delta - add argument and description to function comment
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
WinNtGopBlt (
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL                   *This,
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL                           *BltBuffer, OPTIONAL
 | 
						|
  IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION                   BltOperation,
 | 
						|
  IN  UINTN                                   SourceX,
 | 
						|
  IN  UINTN                                   SourceY,
 | 
						|
  IN  UINTN                                   DestinationX,
 | 
						|
  IN  UINTN                                   DestinationY,
 | 
						|
  IN  UINTN                                   Width,
 | 
						|
  IN  UINTN                                   Height,
 | 
						|
  IN  UINTN                                   Delta         OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  GOP_PRIVATE_DATA              *Private;
 | 
						|
  EFI_TPL                       OriginalTPL;
 | 
						|
  UINTN                         DstY;
 | 
						|
  UINTN                         SrcY;
 | 
						|
  RGBQUAD                       *VScreen;
 | 
						|
  RGBQUAD                       *VScreenSrc;
 | 
						|
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
 | 
						|
  UINTN                         Index;
 | 
						|
  RECT                          Rect;
 | 
						|
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *FillPixel;
 | 
						|
  UINT32                        VerticalResolution;
 | 
						|
  UINT32                        HorizontalResolution;
 | 
						|
 | 
						|
  Private = GOP_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  if ((BltOperation < 0) || (BltOperation >= EfiGraphicsOutputBltOperationMax)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Width == 0 || Height == 0) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // If Delta is zero, then the entire BltBuffer is being used, so Delta
 | 
						|
  // is the number of bytes in each row of BltBuffer.  Since BltBuffer is Width pixels size,
 | 
						|
  // the number of bytes in each row can be computed.
 | 
						|
  //
 | 
						|
  if (Delta == 0) {
 | 
						|
    Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // We need to fill the Virtual Screen buffer with the blt data.
 | 
						|
  // The virtual screen is upside down, as the first row is the bootom row of
 | 
						|
  // the image.
 | 
						|
  //
 | 
						|
  VerticalResolution = This->Mode->Info->VerticalResolution;
 | 
						|
  HorizontalResolution = This->Mode->Info->HorizontalResolution;
 | 
						|
  if (BltOperation == EfiBltVideoToBltBuffer) {
 | 
						|
 | 
						|
    //
 | 
						|
    // Video to BltBuffer: Source is Video, destination is BltBuffer
 | 
						|
    //
 | 
						|
    if (SourceY + Height > VerticalResolution) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if (SourceX + Width > HorizontalResolution) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
 | 
						|
    // We would not want a timer based event (Cursor, ...) to come in while we are
 | 
						|
    // doing this operation.
 | 
						|
    //
 | 
						|
    OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
 | 
						|
 | 
						|
    for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
 | 
						|
      Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + (DstY * Delta) + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
 | 
						|
      VScreen = &Private->VirtualScreen[(VerticalResolution - SrcY - 1) * HorizontalResolution + SourceX];
 | 
						|
      CopyMem (Blt, VScreen, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * Width);
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // BltBuffer to Video: Source is BltBuffer, destination is Video
 | 
						|
    //
 | 
						|
    if (DestinationY + Height > VerticalResolution) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if (DestinationX + Width > HorizontalResolution) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
 | 
						|
    // We would not want a timer based event (Cursor, ...) to come in while we are
 | 
						|
    // doing this operation.
 | 
						|
    //
 | 
						|
    OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
 | 
						|
 | 
						|
    if (BltOperation == EfiBltVideoFill) {
 | 
						|
      FillPixel = BltBuffer;
 | 
						|
      for (Index = 0; Index < Width; Index++) {
 | 
						|
        Private->FillLine[Index] = *FillPixel;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    for (Index = 0; Index < Height; Index++) {
 | 
						|
      if (DestinationY <= SourceY) {
 | 
						|
        SrcY  = SourceY + Index;
 | 
						|
        DstY  = DestinationY + Index;
 | 
						|
      } else {
 | 
						|
        SrcY  = SourceY + Height - Index - 1;
 | 
						|
        DstY  = DestinationY + Height - Index - 1;
 | 
						|
      }
 | 
						|
 | 
						|
      VScreen = &Private->VirtualScreen[(VerticalResolution - DstY - 1) * HorizontalResolution + DestinationX];
 | 
						|
      switch (BltOperation) {
 | 
						|
      case EfiBltBufferToVideo:
 | 
						|
        Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + (SrcY * Delta) + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
 | 
						|
        CopyMem (VScreen, Blt, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
 | 
						|
        break;
 | 
						|
 | 
						|
      case EfiBltVideoToVideo:
 | 
						|
        VScreenSrc = &Private->VirtualScreen[(VerticalResolution - SrcY - 1) * HorizontalResolution + SourceX];
 | 
						|
        CopyMem (VScreen, VScreenSrc, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
 | 
						|
        break;
 | 
						|
 | 
						|
      case EfiBltVideoFill:
 | 
						|
        CopyMem (VScreen, Private->FillLine, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (BltOperation != EfiBltVideoToBltBuffer) {
 | 
						|
    //
 | 
						|
    // Mark the area we just blted as Invalid so WM_PAINT will update.
 | 
						|
    //
 | 
						|
    Rect.left   = DestinationX;
 | 
						|
    Rect.top    = DestinationY;
 | 
						|
    Rect.right  = DestinationX + Width;
 | 
						|
    Rect.bottom = DestinationY + Height;
 | 
						|
    Private->WinNtThunk->InvalidateRect (Private->WindowHandle, &Rect, FALSE);
 | 
						|
 | 
						|
    //
 | 
						|
    // Send the WM_PAINT message to the thread that is drawing the window. We
 | 
						|
    // are in the main thread and the window drawing is in a child thread.
 | 
						|
    // There is a child thread per window. We have no CriticalSection or Mutex
 | 
						|
    // since we write the data and the other thread displays the data. While
 | 
						|
    // we may miss some data for a short period of time this is no different than
 | 
						|
    // a write combining on writes to a frame buffer.
 | 
						|
    //
 | 
						|
 | 
						|
    Private->WinNtThunk->UpdateWindow (Private->WindowHandle);
 | 
						|
  }
 | 
						|
 | 
						|
  gBS->RestoreTPL (OriginalTPL);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Construction and Destruction functions
 | 
						|
//
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
 | 
						|
  @return None
 | 
						|
 | 
						|
**/
 | 
						|
// TODO:    WinNtIo - add argument and description to function comment
 | 
						|
// TODO:    EFI_UNSUPPORTED - add return value to function comment
 | 
						|
// TODO:    EFI_SUCCESS - add return value to function comment
 | 
						|
EFI_STATUS
 | 
						|
WinNtGopSupported (
 | 
						|
  IN  EFI_WIN_NT_IO_PROTOCOL  *WinNtIo
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // Check to see if the IO abstraction represents a device type we support.
 | 
						|
  //
 | 
						|
  // This would be replaced a check of PCI subsystem ID, etc.
 | 
						|
  //
 | 
						|
  if (!CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtGopGuid)) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Win32 Windows event handler.
 | 
						|
 | 
						|
  See Win32 Book
 | 
						|
 | 
						|
  @return See Win32 Book
 | 
						|
 | 
						|
**/
 | 
						|
// TODO:    hwnd - add argument and description to function comment
 | 
						|
// TODO:    iMsg - add argument and description to function comment
 | 
						|
// TODO:    wParam - add argument and description to function comment
 | 
						|
// TODO:    lParam - add argument and description to function comment
 | 
						|
LRESULT
 | 
						|
CALLBACK
 | 
						|
WinNtGopThreadWindowProc (
 | 
						|
  IN  HWND    hwnd,
 | 
						|
  IN  UINT    iMsg,
 | 
						|
  IN  WPARAM  wParam,
 | 
						|
  IN  LPARAM  lParam
 | 
						|
  )
 | 
						|
{
 | 
						|
  GOP_PRIVATE_DATA  *Private;
 | 
						|
  UINTN             Size;
 | 
						|
  HDC               Handle;
 | 
						|
  PAINTSTRUCT       PaintStruct;
 | 
						|
  LPARAM            Index;
 | 
						|
  EFI_INPUT_KEY     Key;
 | 
						|
 | 
						|
  //
 | 
						|
  // BugBug - if there are two instances of this DLL in memory (such as is
 | 
						|
  // the case for ERM), the correct instance of this function may not be called.
 | 
						|
  // This also means that the address of the mTlsIndex value will be wrong, and
 | 
						|
  // the value may be wrong too.
 | 
						|
  //
 | 
						|
 | 
						|
 | 
						|
  //
 | 
						|
  // Use mTlsIndex global to get a Thread Local Storage version of Private.
 | 
						|
  // This works since each Gop protocol has a unique Private data instance and
 | 
						|
  // a unique thread.
 | 
						|
  //
 | 
						|
  Private = mWinNt->TlsGetValue (mTlsIndex);
 | 
						|
  ASSERT (NULL != Private);
 | 
						|
 | 
						|
  switch (iMsg) {
 | 
						|
  case WM_CREATE:
 | 
						|
    Size = Private->GraphicsOutput.Mode->Info->HorizontalResolution * Private->GraphicsOutput.Mode->Info->VerticalResolution * sizeof (RGBQUAD);
 | 
						|
 | 
						|
    //
 | 
						|
    // Allocate DIB frame buffer directly from NT for performance enhancement
 | 
						|
    // This buffer is the virtual screen/frame buffer. This buffer is not the
 | 
						|
    // same a a frame buffer. The first fow of this buffer will be the bottom
 | 
						|
    // line of the image. This is an artifact of the way we draw to the screen.
 | 
						|
    //
 | 
						|
    Private->VirtualScreenInfo = Private->WinNtThunk->HeapAlloc (
 | 
						|
                                                        Private->WinNtThunk->GetProcessHeap (),
 | 
						|
                                                        HEAP_ZERO_MEMORY,
 | 
						|
                                                        Size
 | 
						|
                                                        );
 | 
						|
 | 
						|
    Private->VirtualScreenInfo->bV4Size           = sizeof (BITMAPV4HEADER);
 | 
						|
    Private->VirtualScreenInfo->bV4Width          = Private->GraphicsOutput.Mode->Info->HorizontalResolution;
 | 
						|
    Private->VirtualScreenInfo->bV4Height         = Private->GraphicsOutput.Mode->Info->VerticalResolution;
 | 
						|
    Private->VirtualScreenInfo->bV4Planes         = 1;
 | 
						|
    Private->VirtualScreenInfo->bV4BitCount       = 32;
 | 
						|
    //
 | 
						|
    // uncompressed
 | 
						|
    //
 | 
						|
    Private->VirtualScreenInfo->bV4V4Compression  = BI_RGB;
 | 
						|
    Private->VirtualScreen = (RGBQUAD *) (Private->VirtualScreenInfo + 1);
 | 
						|
    return 0;
 | 
						|
 | 
						|
  case WM_PAINT:
 | 
						|
    //
 | 
						|
    // I have not found a way to convert hwnd into a Private context. So for
 | 
						|
    // now we use this API to convert hwnd to Private data.
 | 
						|
    //
 | 
						|
 | 
						|
    Handle = mWinNt->BeginPaint (hwnd, &PaintStruct);
 | 
						|
 | 
						|
    mWinNt->SetDIBitsToDevice (
 | 
						|
              Handle,                                     // Destination Device Context
 | 
						|
              0,                                          // Destination X - 0
 | 
						|
              0,                                          // Destination Y - 0
 | 
						|
              Private->GraphicsOutput.Mode->Info->HorizontalResolution,              // Width
 | 
						|
              Private->GraphicsOutput.Mode->Info->VerticalResolution,                // Height
 | 
						|
              0,                                          // Source X
 | 
						|
              0,                                          // Source Y
 | 
						|
              0,                                          // DIB Start Scan Line
 | 
						|
              Private->GraphicsOutput.Mode->Info->VerticalResolution,                // Number of scan lines
 | 
						|
              Private->VirtualScreen,                     // Address of array of DIB bits
 | 
						|
              (BITMAPINFO *) Private->VirtualScreenInfo,  // Address of structure with bitmap info
 | 
						|
              DIB_RGB_COLORS                              // RGB or palette indexes
 | 
						|
              );
 | 
						|
 | 
						|
    mWinNt->EndPaint (hwnd, &PaintStruct);
 | 
						|
    return 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // F10 and the ALT key do not create a WM_KEYDOWN message, thus this special case
 | 
						|
  // WM_SYSKEYDOWN is posted when F10 is pressed or 
 | 
						|
  // holds down ALT key and then presses another key.
 | 
						|
  //
 | 
						|
  case WM_SYSKEYDOWN:
 | 
						|
    Key.ScanCode = 0;
 | 
						|
    switch (wParam) {
 | 
						|
    case VK_F10:
 | 
						|
      Key.ScanCode    = SCAN_F10;
 | 
						|
      Key.UnicodeChar = 0;
 | 
						|
      GopPrivateAddQ (Private, Key);
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((lParam & GOP_ALT_KEY_PRESSED) == GOP_ALT_KEY_PRESSED) {
 | 
						|
      //
 | 
						|
      // ALT is pressed with another key pressed
 | 
						|
      //
 | 
						|
      WinNtGopConvertParamToEfiKey (Private, &wParam, &Key);
 | 
						|
 | 
						|
      if ((lParam & GOP_EXTENDED_KEY) == GOP_EXTENDED_KEY) {
 | 
						|
        Private->RightAlt = TRUE;
 | 
						|
      } else {
 | 
						|
        Private->LeftAlt = TRUE;
 | 
						|
      }
 | 
						|
 | 
						|
      if (Private->RightAlt && Private->LeftAlt) {
 | 
						|
        Private->LeftAlt = FALSE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (Key.ScanCode != 0) {
 | 
						|
      Key.UnicodeChar = 0;
 | 
						|
      GopPrivateAddQ (Private, Key);
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
 | 
						|
  case WM_SYSKEYUP:
 | 
						|
    if ((lParam & GOP_ALT_KEY_PRESSED) == GOP_ALT_KEY_PRESSED) {
 | 
						|
      //
 | 
						|
      // ALT is pressed with another key released
 | 
						|
      //
 | 
						|
      WinNtGopConvertParamToEfiKeyShiftState (Private, &wParam, FALSE);  
 | 
						|
      //
 | 
						|
      // Actually ALT key is still held down here.
 | 
						|
      // Change the ALT key state when another key is released
 | 
						|
      // by user because we did not find a better solution to
 | 
						|
      // get a released ALT key. 
 | 
						|
      //
 | 
						|
      Private->RightAlt = FALSE;
 | 
						|
      Private->LeftAlt = FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
 | 
						|
 | 
						|
  case WM_KEYDOWN:
 | 
						|
    Key.ScanCode = 0;
 | 
						|
    WinNtGopConvertParamToEfiKey (Private, &wParam, &Key);
 | 
						|
    if (Key.ScanCode != 0) {
 | 
						|
      Key.UnicodeChar = 0;
 | 
						|
      GopPrivateAddQ (Private, Key);
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
 | 
						|
  case WM_KEYUP:
 | 
						|
    WinNtGopConvertParamToEfiKeyShiftState (Private, &wParam, FALSE);  
 | 
						|
    return 0;
 | 
						|
 | 
						|
  case WM_CHAR:
 | 
						|
    //
 | 
						|
    // The ESC key also generate WM_CHAR.
 | 
						|
    //
 | 
						|
    if (wParam == 0x1B) {
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    for (Index = 0; Index < (lParam & 0xffff); Index++) {
 | 
						|
      if (wParam != 0) {
 | 
						|
        Key.UnicodeChar = (CHAR16) wParam;
 | 
						|
        Key.ScanCode    = 0;
 | 
						|
        GopPrivateAddQ (Private, Key);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
 | 
						|
  case WM_CLOSE:
 | 
						|
    //
 | 
						|
    // This close message is issued by user, core is not aware of this,
 | 
						|
    // so don't release the window display resource, just hide the window.
 | 
						|
    //
 | 
						|
    Private->WinNtThunk->ShowWindow (Private->WindowHandle, SW_HIDE);
 | 
						|
    return 0;
 | 
						|
 | 
						|
  case WM_DESTROY:
 | 
						|
    mWinNt->DestroyWindow (hwnd);
 | 
						|
    mWinNt->PostQuitMessage (0);
 | 
						|
 | 
						|
    mWinNt->HeapFree (Private->WinNtThunk->GetProcessHeap (), 0, Private->VirtualScreenInfo);
 | 
						|
 | 
						|
    mWinNt->ExitThread (0);
 | 
						|
    return 0;
 | 
						|
 | 
						|
  default:
 | 
						|
    break;
 | 
						|
  };
 | 
						|
 | 
						|
  return mWinNt->DefWindowProc (hwnd, iMsg, wParam, lParam);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  This thread simulates the end of WinMain () aplication. Each Winow nededs
 | 
						|
  to process it's events. The messages are dispatched to
 | 
						|
  WinNtGopThreadWindowProc ().
 | 
						|
  Be very careful sine WinNtGopThreadWinMain () and WinNtGopThreadWindowProc ()
 | 
						|
  are running in a seperate thread. We have to do this to process the events.
 | 
						|
 | 
						|
  @param  lpParameter            Handle of window to manage.
 | 
						|
 | 
						|
  @return if a WM_QUIT message is returned exit.
 | 
						|
 | 
						|
**/
 | 
						|
DWORD
 | 
						|
WINAPI
 | 
						|
WinNtGopThreadWinMain (
 | 
						|
  LPVOID    lpParameter
 | 
						|
  )
 | 
						|
{
 | 
						|
  MSG               Message;
 | 
						|
  GOP_PRIVATE_DATA  *Private;
 | 
						|
  RECT              Rect;
 | 
						|
 | 
						|
  Private = (GOP_PRIVATE_DATA *) lpParameter;
 | 
						|
  ASSERT (NULL != Private);
 | 
						|
 | 
						|
  //
 | 
						|
  // Since each thread has unique private data, save the private data in Thread
 | 
						|
  // Local Storage slot. Then the shared global mTlsIndex can be used to get
 | 
						|
  // thread specific context.
 | 
						|
  //
 | 
						|
  Private->WinNtThunk->TlsSetValue (mTlsIndex, Private);
 | 
						|
 | 
						|
  Private->ThreadId                   = Private->WinNtThunk->GetCurrentThreadId ();
 | 
						|
 | 
						|
  Private->WindowsClass.cbSize        = sizeof (WNDCLASSEX);
 | 
						|
  Private->WindowsClass.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
 | 
						|
  Private->WindowsClass.lpfnWndProc   = WinNtGopThreadWindowProc;
 | 
						|
  Private->WindowsClass.cbClsExtra    = 0;
 | 
						|
  Private->WindowsClass.cbWndExtra    = 0;
 | 
						|
  Private->WindowsClass.hInstance     = NULL;
 | 
						|
  Private->WindowsClass.hIcon         = Private->WinNtThunk->LoadIcon (NULL, IDI_APPLICATION);
 | 
						|
  Private->WindowsClass.hCursor       = Private->WinNtThunk->LoadCursor (NULL, IDC_ARROW);
 | 
						|
  Private->WindowsClass.hbrBackground = (HBRUSH) COLOR_WINDOW;
 | 
						|
  Private->WindowsClass.lpszMenuName  = NULL;
 | 
						|
  Private->WindowsClass.lpszClassName = WIN_NT_GOP_CLASS_NAME;
 | 
						|
  Private->WindowsClass.hIconSm       = Private->WinNtThunk->LoadIcon (NULL, IDI_APPLICATION);
 | 
						|
 | 
						|
  //
 | 
						|
  // This call will fail after the first time, but thats O.K. since we only need
 | 
						|
  // WIN_NT_GOP_CLASS_NAME to exist to create the window.
 | 
						|
  //
 | 
						|
  // Note: Multiple instances of this DLL will use the same instance of this
 | 
						|
  // Class, including the callback function, unless the Class is unregistered and
 | 
						|
  // successfully registered again.
 | 
						|
  //
 | 
						|
  Private->WinNtThunk->RegisterClassEx (&Private->WindowsClass);
 | 
						|
 | 
						|
  //
 | 
						|
  // Setting Rect values to allow for the AdjustWindowRect to provide
 | 
						|
  // us the correct sizes for the client area when doing the CreateWindowEx
 | 
						|
  //
 | 
						|
  Rect.top    = 0;
 | 
						|
  Rect.bottom = Private->GraphicsOutput.Mode->Info->VerticalResolution;
 | 
						|
  Rect.left   = 0;
 | 
						|
  Rect.right  = Private->GraphicsOutput.Mode->Info->HorizontalResolution;
 | 
						|
 | 
						|
  Private->WinNtThunk->AdjustWindowRect (&Rect, WS_OVERLAPPEDWINDOW, 0);
 | 
						|
 | 
						|
  Private->WindowHandle = Private->WinNtThunk->CreateWindowEx (
 | 
						|
                                                0,
 | 
						|
                                                WIN_NT_GOP_CLASS_NAME,
 | 
						|
                                                Private->WindowName,
 | 
						|
                                                WS_OVERLAPPEDWINDOW,
 | 
						|
                                                CW_USEDEFAULT,
 | 
						|
                                                CW_USEDEFAULT,
 | 
						|
                                                Rect.right - Rect.left,
 | 
						|
                                                Rect.bottom - Rect.top,
 | 
						|
                                                NULL,
 | 
						|
                                                NULL,
 | 
						|
                                                NULL,
 | 
						|
                                                (VOID **)&Private
 | 
						|
                                                );
 | 
						|
 | 
						|
  //
 | 
						|
  // The reset of this thread is the standard winows program. We need a sperate
 | 
						|
  // thread since we must process the message loop to make windows act like
 | 
						|
  // windows.
 | 
						|
  //
 | 
						|
 | 
						|
  Private->WinNtThunk->ShowWindow (Private->WindowHandle, SW_SHOW);
 | 
						|
  Private->WinNtThunk->UpdateWindow (Private->WindowHandle);
 | 
						|
 | 
						|
  //
 | 
						|
  // Let the main thread get some work done
 | 
						|
  //
 | 
						|
  Private->WinNtThunk->ReleaseSemaphore (Private->ThreadInited, 1, NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // This is the message loop that all Windows programs need.
 | 
						|
  //
 | 
						|
  while (Private->WinNtThunk->GetMessage (&Message, Private->WindowHandle, 0, 0)) {
 | 
						|
    Private->WinNtThunk->TranslateMessage (&Message);
 | 
						|
    Private->WinNtThunk->DispatchMessage (&Message);
 | 
						|
  }
 | 
						|
 | 
						|
  return Message.wParam;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  TODO: Add function description
 | 
						|
 | 
						|
  @param  Private                TODO: add argument description
 | 
						|
  @param  HorizontalResolution   TODO: add argument description
 | 
						|
  @param  VerticalResolution     TODO: add argument description
 | 
						|
  @param  ColorDepth             TODO: add argument description
 | 
						|
  @param  RefreshRate            TODO: add argument description
 | 
						|
 | 
						|
  @return TODO: add return values
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
WinNtGopStartWindow (
 | 
						|
  IN  GOP_PRIVATE_DATA    *Private,
 | 
						|
  IN  UINT32              HorizontalResolution,
 | 
						|
  IN  UINT32              VerticalResolution,
 | 
						|
  IN  UINT32              ColorDepth,
 | 
						|
  IN  UINT32              RefreshRate
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS          Status;
 | 
						|
  DWORD               NewThreadId;
 | 
						|
 | 
						|
  mWinNt  = Private->WinNtThunk;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize a Thread Local Storge variable slot. We use TLS to get the
 | 
						|
  // correct Private data instance into the windows thread.
 | 
						|
  //
 | 
						|
  if (mTlsIndex == TLS_OUT_OF_INDEXES) {
 | 
						|
    ASSERT (0 == mTlsIndexUseCount);
 | 
						|
    mTlsIndex = Private->WinNtThunk->TlsAlloc ();
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // always increase the use count!
 | 
						|
  //
 | 
						|
  mTlsIndexUseCount++;
 | 
						|
 | 
						|
  //
 | 
						|
  // Register to be notified on exit boot services so we can destroy the window.
 | 
						|
  //
 | 
						|
  Status = gBS->CreateEventEx (
 | 
						|
                  EVT_NOTIFY_SIGNAL,
 | 
						|
                  TPL_CALLBACK,
 | 
						|
                  KillNtGopThread,
 | 
						|
                  Private,
 | 
						|
                  &gEfiEventExitBootServicesGuid,
 | 
						|
                  &mGopScreenExitBootServicesEvent
 | 
						|
                  );
 | 
						|
 | 
						|
  Private->ThreadInited = Private->WinNtThunk->CreateSemaphore (NULL, 0, 1, NULL);
 | 
						|
  Private->ThreadHandle = Private->WinNtThunk->CreateThread (
 | 
						|
                                                NULL,
 | 
						|
                                                0,
 | 
						|
                                                WinNtGopThreadWinMain,
 | 
						|
                                                (VOID *) Private,
 | 
						|
                                                0,
 | 
						|
                                                &NewThreadId
 | 
						|
                                                );
 | 
						|
 | 
						|
  //
 | 
						|
  // The other thread has entered the windows message loop so we can
 | 
						|
  // continue our initialization.
 | 
						|
  //
 | 
						|
  Private->WinNtThunk->WaitForSingleObject (Private->ThreadInited, INFINITE);
 | 
						|
  Private->WinNtThunk->CloseHandle (Private->ThreadInited);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
 | 
						|
  @return None
 | 
						|
 | 
						|
**/
 | 
						|
// TODO:    Private - add argument and description to function comment
 | 
						|
// TODO:    EFI_SUCCESS - add return value to function comment
 | 
						|
EFI_STATUS
 | 
						|
WinNtGopConstructor (
 | 
						|
  GOP_PRIVATE_DATA    *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  Private->ModeData = mGopModeData;
 | 
						|
 | 
						|
  Private->GraphicsOutput.QueryMode = WinNtGopQuerytMode;
 | 
						|
  Private->GraphicsOutput.SetMode = WinNtGopSetMode;
 | 
						|
  Private->GraphicsOutput.Blt            = WinNtGopBlt;
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate buffer for Graphics Output Protocol mode information
 | 
						|
  //
 | 
						|
  Private->GraphicsOutput.Mode = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE));
 | 
						|
  if (Private->GraphicsOutput.Mode == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  Private->GraphicsOutput.Mode->Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
 | 
						|
  if (Private->GraphicsOutput.Mode->Info == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Private->GraphicsOutput.Mode->MaxMode = sizeof(mGopModeData) / sizeof(GOP_MODE_DATA);
 | 
						|
  //
 | 
						|
  // Till now, we have no idea about the window size.
 | 
						|
  //
 | 
						|
  Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
 | 
						|
  Private->GraphicsOutput.Mode->Info->Version = 0;
 | 
						|
  Private->GraphicsOutput.Mode->Info->HorizontalResolution = 0;
 | 
						|
  Private->GraphicsOutput.Mode->Info->VerticalResolution = 0;
 | 
						|
  Private->GraphicsOutput.Mode->Info->PixelFormat = PixelBltOnly;
 | 
						|
  Private->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
 | 
						|
  Private->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;
 | 
						|
  Private->GraphicsOutput.Mode->FrameBufferSize = 0;
 | 
						|
 | 
						|
  Private->HardwareNeedsStarting  = TRUE;
 | 
						|
  Private->FillLine               = NULL;
 | 
						|
 | 
						|
  WinNtGopInitializeSimpleTextInForWindow (Private);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
 | 
						|
  @return None
 | 
						|
 | 
						|
**/
 | 
						|
// TODO:    Private - add argument and description to function comment
 | 
						|
// TODO:    EFI_SUCCESS - add return value to function comment
 | 
						|
EFI_STATUS
 | 
						|
WinNtGopDestructor (
 | 
						|
  GOP_PRIVATE_DATA     *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (!Private->HardwareNeedsStarting) {
 | 
						|
    //
 | 
						|
    // BugBug: Shutdown GOP Hardware and any child devices.
 | 
						|
    //
 | 
						|
    Private->WinNtThunk->SendMessage (Private->WindowHandle, WM_DESTROY, 0, 0);
 | 
						|
    Private->WinNtThunk->CloseHandle (Private->ThreadHandle);
 | 
						|
 | 
						|
    mTlsIndexUseCount--;
 | 
						|
 | 
						|
    //
 | 
						|
    // The callback function for another window could still be called,
 | 
						|
    // so we need to make sure there are no more users of mTlsIndex.
 | 
						|
    //
 | 
						|
    if (0 == mTlsIndexUseCount) {
 | 
						|
      ASSERT (TLS_OUT_OF_INDEXES != mTlsIndex);
 | 
						|
 | 
						|
      Private->WinNtThunk->TlsFree (mTlsIndex);
 | 
						|
      mTlsIndex = TLS_OUT_OF_INDEXES;
 | 
						|
 | 
						|
      Private->WinNtThunk->UnregisterClass (
 | 
						|
                              Private->WindowsClass.lpszClassName,
 | 
						|
                              Private->WindowsClass.hInstance
 | 
						|
                              );
 | 
						|
    }
 | 
						|
 | 
						|
    WinNtGopDestroySimpleTextInForWindow (Private);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Free graphics output protocol occupied resource
 | 
						|
  //
 | 
						|
  if (Private->GraphicsOutput.Mode != NULL) {
 | 
						|
    if (Private->GraphicsOutput.Mode->Info != NULL) {
 | 
						|
      FreePool (Private->GraphicsOutput.Mode->Info);
 | 
						|
    }
 | 
						|
    FreePool (Private->GraphicsOutput.Mode);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  This is the GOP screen's callback notification function for exit-boot-services.
 | 
						|
  All we do here is call WinNtGopDestructor().
 | 
						|
 | 
						|
  @param  Event                  not used
 | 
						|
  @param  Context                pointer to the Private structure.
 | 
						|
 | 
						|
  @return None.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
KillNtGopThread (
 | 
						|
  IN EFI_EVENT  Event,
 | 
						|
  IN VOID       *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  WinNtGopDestructor (Context);
 | 
						|
}
 |