From: klu2 Date: Wed, 27 Jun 2007 06:48:58 +0000 (+0000) Subject: Add WinNtGop driver into Nt32Pkg X-Git-Tag: edk2-stable201903~23171 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=c9fc89a313e0955d3eb8baf3bbfd8bb7d450ad7c Add WinNtGop driver into Nt32Pkg git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2784 6f19259b-4bc3-4df7-8a09-765794883524 --- diff --git a/Nt32Pkg/Nt32.dsc b/Nt32Pkg/Nt32.dsc index 61b2d83713..28e046fcd2 100644 --- a/Nt32Pkg/Nt32.dsc +++ b/Nt32Pkg/Nt32.dsc @@ -411,3 +411,4 @@ $(WORKSPACE)\Nt32Pkg\WinNtBusDriverDxe\WinNtBusDriver.inf $(WORKSPACE)\Nt32Pkg\WinNtConsoleDxe\WinNtConsole.inf $(WORKSPACE)\Nt32Pkg\WinNtSimpleFileSystemDxe\WinNtSimpleFileSystem.inf + $(WORKSPACE)\Nt32Pkg\WinNtGopDxe\WinNtGop.inf diff --git a/Nt32Pkg/WinNtGopDxe/ComponentName.c b/Nt32Pkg/WinNtGopDxe/ComponentName.c new file mode 100644 index 0000000000..952db00dc2 --- /dev/null +++ b/Nt32Pkg/WinNtGopDxe/ComponentName.c @@ -0,0 +1,224 @@ +/** @file + +Copyright (c) 2006, 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: + + ComponentName.c + +Abstract: + + +**/ + +// +// The package level header files this module uses +// +#include +#include +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +#include +#include +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include + +#include "WinNtGop.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +WinNtGopComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +WinNtGopComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gWinNtGopComponentName = { + WinNtGopComponentNameGetDriverName, + WinNtGopComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mWinNtGopDriverNameTable[] = { + { "eng", L"Windows GOP Driver" }, + { NULL , NULL } +}; + + +/** + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL + instance. + @param Language A pointer to a three character ISO 639-2 language + identifier. This is the language of the driver + name that that the caller is requesting, and it + must match one of the languages specified in + SupportedLanguages. The number of languages + supported by a driver is up to the driver writer. + @param DriverName A pointer to the Unicode string to return. This + Unicode string is the name of the driver specified + by This in the language specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER DriverName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + +**/ +EFI_STATUS +EFIAPI +WinNtGopComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString ( + Language, + gWinNtGopComponentName.SupportedLanguages, + mWinNtGopDriverNameTable, + DriverName + ); +} + + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL + instance. + @param ControllerHandle The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + @param ChildHandle The handle of the child controller to retrieve the + name of. This is an optional parameter that may + be NULL. It will be NULL for device drivers. It + will also be NULL for a bus drivers that wish to + retrieve the name of the bus controller. It will + not be NULL for a bus driver that wishes to + retrieve the name of a child controller. + @param Language A pointer to a three character ISO 639-2 language + identifier. This is the language of the + controller name that that the caller is + requesting, and it must match one of the languages + specified in SupportedLanguages. The number of + languages supported by a driver is up to the + driver writer. + @param ControllerName A pointer to the Unicode string to return. This + Unicode string is the name of the controller + specified by ControllerHandle and ChildHandle in + the language specified by Language from the point + of view of the driver specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the driver + specified by This was returned in DriverName. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + +**/ +EFI_STATUS +EFIAPI +WinNtGopComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + GOP_PRIVATE_DATA *Private; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + // + // Make sure this driver is currently managing ControllerHandle + // + Status = EfiTestManagedDevice ( + ControllerHandle, + gWinNtGopDriverBinding.DriverBindingHandle, + &gEfiWinNtIoProtocolGuid + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + // + // Get our context back + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiGraphicsOutputProtocolGuid, + &GraphicsOutput, + gWinNtGopDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Private = GOP_PRIVATE_DATA_FROM_THIS (GraphicsOutput); + + return LookupUnicodeString ( + Language, + gWinNtGopComponentName.SupportedLanguages, + Private->ControllerNameTable, + ControllerName + ); +} diff --git a/Nt32Pkg/WinNtGopDxe/WinNtGop.h b/Nt32Pkg/WinNtGopDxe/WinNtGop.h new file mode 100644 index 0000000000..cc7283ebf6 --- /dev/null +++ b/Nt32Pkg/WinNtGopDxe/WinNtGop.h @@ -0,0 +1,326 @@ +/** @file + +Copyright (c) 2006, 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: + + WinNtGop.h + +Abstract: + + Private data for the Gop driver that is bound to the WinNt Thunk protocol + + +**/ + +#ifndef _WIN_NT_GOP_H_ +#define _WIN_NT_GOP_H_ + +// +// Include common header file for this module. +// +#include "CommonHeader.h" + +//@MT:#include "EfiWinNT.h" +//@MT:#include "Tiano.h" +//@MT:#include "EfiDriverLib.h" + +// +// Driver Consumed Protocols +// +//@MT:#include EFI_PROTOCOL_DEFINITION (DevicePath) +//@MT:#include EFI_PROTOCOL_DEFINITION (WinNtIo) + +// +// Driver Produced Protocols +// +//@MT:#include EFI_PROTOCOL_DEFINITION (DriverBinding) +//@MT:#include EFI_PROTOCOL_DEFINITION (ComponentName) +//@MT:#include EFI_PROTOCOL_DEFINITION (GraphicsOutput) +//@MT:#include "LinkedList.h" + +#define MAX_Q 256 + +typedef struct { + UINTN Front; + UINTN Rear; + UINTN Count; + EFI_INPUT_KEY Q[MAX_Q]; +} GOP_QUEUE_FIXED; + +#define WIN_NT_GOP_CLASS_NAME L"WinNtGopWindow" + +#define GOP_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('S', 'g', 'o', 'N') + +#define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER 0xffff + +typedef struct { + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + UINT32 ColorDepth; + UINT32 RefreshRate; +} GOP_MODE_DATA; + +typedef struct { + UINT64 Signature; + + EFI_HANDLE Handle; + EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutput; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleTextIn; + + EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk; + + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + + // + // GOP Private Data for QueryMode () + // + GOP_MODE_DATA *ModeData; + + // + // GOP Private Data knowing when to start hardware + // + BOOLEAN HardwareNeedsStarting; + + CHAR16 *WindowName; + CHAR16 Buffer[160]; + + HANDLE ThreadInited; // Semaphore + HANDLE ThreadHandle; // Thread + DWORD ThreadId; + + HWND WindowHandle; + WNDCLASSEX WindowsClass; + + // + // This screen is used to redraw the scree when windows events happen. It's + // updated in the main thread and displayed in the windows thread. + // + BITMAPV4HEADER *VirtualScreenInfo; + RGBQUAD *VirtualScreen; + + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *FillLine; + + // + // Keyboard Queue used by Simple Text In. WinProc thread adds, and main + // thread removes. + // + CRITICAL_SECTION QCriticalSection; + GOP_QUEUE_FIXED Queue; + +} GOP_PRIVATE_DATA; + +#define GOP_PRIVATE_DATA_FROM_THIS(a) \ + CR(a, GOP_PRIVATE_DATA, GraphicsOutput, GOP_PRIVATE_DATA_SIGNATURE) + +#define GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS(a) \ + CR(a, GOP_PRIVATE_DATA, SimpleTextIn, GOP_PRIVATE_DATA_SIGNATURE) + +// +// Global Protocol Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gWinNtGopDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gWinNtGopComponentName; + +// +// Gop Hardware abstraction internal worker functions +// + +/** + TODO: Add function description + + @param WinNtIo TODO: add argument description + + @return TODO: add return values + +**/ +EFI_STATUS +WinNtGopSupported ( + IN EFI_WIN_NT_IO_PROTOCOL *WinNtIo + ) +; + + +/** + TODO: Add function description + + @param Private TODO: add argument description + + @return TODO: add return values + +**/ +EFI_STATUS +WinNtGopConstructor ( + IN GOP_PRIVATE_DATA *Private + ) +; + + +/** + TODO: Add function description + + @param Private TODO: add argument description + + @return TODO: add return values + +**/ +EFI_STATUS +WinNtGopDestructor ( + IN GOP_PRIVATE_DATA *Private + ) +; + +// +// EFI 1.1 driver model prototypes for Win NT GOP +// + + +/** + TODO: Add function description + + @param ImageHandle TODO: add argument description + @param SystemTable TODO: add argument description + + @return TODO: add return values + +**/ +EFI_STATUS +EFIAPI +WinNtGopInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + + +/** + TODO: Add function description + + @param This TODO: add argument description + @param Handle TODO: add argument description + @param RemainingDevicePath TODO: add argument description + + @return TODO: add return values + +**/ +EFI_STATUS +EFIAPI +WinNtGopDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + + +/** + TODO: Add function description + + @param This TODO: add argument description + @param Handle TODO: add argument description + @param RemainingDevicePath TODO: add argument description + + @return TODO: add return values + +**/ +EFI_STATUS +EFIAPI +WinNtGopDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + + +/** + TODO: Add function description + + @param This TODO: add argument description + @param Handle TODO: add argument description + @param NumberOfChildren TODO: add argument description + @param ChildHandleBuffer TODO: add argument description + + @return TODO: add return values + +**/ +EFI_STATUS +EFIAPI +WinNtGopDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +; + + +/** + TODO: Add function description + + @param Private TODO: add argument description + @param Key TODO: add argument description + + @return TODO: add return values + +**/ +EFI_STATUS +GopPrivateAddQ ( + IN GOP_PRIVATE_DATA *Private, + IN EFI_INPUT_KEY Key + ) +; + + +/** + TODO: Add function description + + @param Private TODO: add argument description + + @return TODO: add return values + +**/ +EFI_STATUS +WinNtGopInitializeSimpleTextInForWindow ( + IN GOP_PRIVATE_DATA *Private + ) +; + + +/** + TODO: Add function description + + @param Private TODO: add argument description + + @return TODO: add return values + +**/ +EFI_STATUS +WinNtGopDestroySimpleTextInForWindow ( + IN GOP_PRIVATE_DATA *Private + ) +; + + +/** + TODO: Add function description + + @param String TODO: add argument description + + @return TODO: add return values + +**/ +UINTN +Atoi ( + IN CHAR16 *String + ) +; + +#endif diff --git a/Nt32Pkg/WinNtGopDxe/WinNtGop.inf b/Nt32Pkg/WinNtGopDxe/WinNtGop.inf new file mode 100644 index 0000000000..7130ba3930 --- /dev/null +++ b/Nt32Pkg/WinNtGopDxe/WinNtGop.inf @@ -0,0 +1,119 @@ +#/** @file +# Gop Driver +# +# GOP is short hand for UEFI Graphics Output protocol. +# This file is a verision of GopIo the uses WinNtThunk system calls as an IO +# abstraction. For a PCI device WinNtIo would be replaced with +# a PCI IO abstraction that abstracted a specific PCI device. +# Copyright (c) 2006 - 2007, 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. +# +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = WinNtGop + FILE_GUID = 29b3c4c6-e5aa-49e4-8ce0-2772f782ddc2 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + + ENTRY_POINT = InitializeWinNtGop + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 +# +# DRIVER_BINDING = gWinNtGopDriverBinding +# COMPONENT_NAME = gWinNtGopComponentName +# + +################################################################################ +# +# Sources Section - list of files that are required for the build to succeed. +# +################################################################################ + +[Sources.common] + WinNtGopDriver.c + ComponentName.c + WinNtGop.h + WinNtGopInput.c + WinNtGopScreen.c + +################################################################################ +# +# Includes Section - list of Include locations that are required for +# this module. +# +################################################################################ + +[Includes] + $(WORKSPACE)/MdePkg/Include/Library + +################################################################################ +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +################################################################################ + +[Packages] + Nt32Pkg/Nt32Pkg.dec + MdePkg/MdePkg.dec + + +################################################################################ +# +# Library Class Section - list of Library Classes that are required for +# this module. +# +################################################################################ + +[LibraryClasses] + MemoryAllocationLib + UefiBootServicesTableLib + BaseMemoryLib + UefiLib + UefiDriverEntryPoint + BaseLib + DebugLib + + +################################################################################ +# +# Guid C Name Section - list of Guids that this module uses or produces. +# +################################################################################ + +[Guids] + gEfiEventExitBootServicesGuid # SOMETIMES_CONSUMED Create Event: EVENT_GROUP_GUID + gEfiWinNtGopGuid # ALWAYS_CONSUMED + + +################################################################################ +# +# Protocol C Name Section - list of Protocol and Protocol Notify C Names +# that this module uses or produces. +# +################################################################################ + +[Protocols] + gEfiGraphicsOutputProtocolGuid # PROTOCOL BY_START + gEfiSimpleTextInProtocolGuid # PROTOCOL BY_START + gEfiWinNtIoProtocolGuid # PROTOCOL TO_START + diff --git a/Nt32Pkg/WinNtGopDxe/WinNtGopDriver.c b/Nt32Pkg/WinNtGopDxe/WinNtGopDriver.c new file mode 100644 index 0000000000..86b6d19ebb --- /dev/null +++ b/Nt32Pkg/WinNtGopDxe/WinNtGopDriver.c @@ -0,0 +1,378 @@ +/** @file + +Copyright (c) 2006 - 2007, 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: + + WinNtGopDriver.c + +Abstract: + + This file implements the UEFI Device Driver model requirements for GOP + + GOP is short hand for Graphics Output Protocol. + + +**/ + +// +// The package level header files this module uses +// +#include +#include +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +#include +#include +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include + +#include "WinNtGop.h" + +EFI_DRIVER_BINDING_PROTOCOL gWinNtGopDriverBinding = { + WinNtGopDriverBindingSupported, + WinNtGopDriverBindingStart, + WinNtGopDriverBindingStop, + 0xa, + NULL, + NULL +}; + +/** + The user Entry Point for module WinNtGop. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializeWinNtGop( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallAllDriverProtocols ( + ImageHandle, + SystemTable, + &gWinNtGopDriverBinding, + ImageHandle, + &gWinNtGopComponentName, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + + return Status; +} + +/** + + + @return None + +**/ +// TODO: This - add argument and description to function comment +// TODO: Handle - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +EFI_STATUS +EFIAPI +WinNtGopDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + &WinNtIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WinNtGopSupported (WinNtIo); + + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + return Status; +} + + +/** + + + @return None + +**/ +// TODO: This - add argument and description to function comment +// TODO: Handle - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +EFI_STATUS +EFIAPI +WinNtGopDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + EFI_STATUS Status; + GOP_PRIVATE_DATA *Private; + + // + // Grab the protocols we need + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + &WinNtIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Allocate Private context data for SGO inteface. + // + Private = NULL; + Private = AllocatePool (sizeof (GOP_PRIVATE_DATA)); + if (Private == NULL) { + goto Done; + } + // + // Set up context record + // + Private->Signature = GOP_PRIVATE_DATA_SIGNATURE; + Private->Handle = Handle; + Private->WinNtThunk = WinNtIo->WinNtThunk; + + Private->ControllerNameTable = NULL; + + AddUnicodeString ( + "eng", + gWinNtGopComponentName.SupportedLanguages, + &Private->ControllerNameTable, + WinNtIo->EnvString + ); + + Private->WindowName = WinNtIo->EnvString; + + Status = WinNtGopConstructor (Private); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Publish the Gop interface to the world + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Private->Handle, + &gEfiGraphicsOutputProtocolGuid, + &Private->GraphicsOutput, + &gEfiSimpleTextInProtocolGuid, + &Private->SimpleTextIn, + NULL + ); + +Done: + if (EFI_ERROR (Status)) { + + gBS->CloseProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + if (Private != NULL) { + // + // On Error Free back private data + // + if (Private->ControllerNameTable != NULL) { + FreeUnicodeStringTable (Private->ControllerNameTable); + } + + FreePool (Private); + } + } + + return Status; +} + + +/** + + + @return None + +**/ +// TODO: This - add argument and description to function comment +// TODO: Handle - add argument and description to function comment +// TODO: NumberOfChildren - add argument and description to function comment +// TODO: ChildHandleBuffer - add argument and description to function comment +// TODO: EFI_NOT_STARTED - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +EFI_STATUS +EFIAPI +WinNtGopDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_STATUS Status; + GOP_PRIVATE_DATA *Private; + + Status = gBS->OpenProtocol ( + Handle, + &gEfiGraphicsOutputProtocolGuid, + &GraphicsOutput, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + // + // If the GOP interface does not exist the driver is not started + // + return EFI_NOT_STARTED; + } + + // + // Get our private context information + // + Private = GOP_PRIVATE_DATA_FROM_THIS (GraphicsOutput); + + // + // Remove the SGO interface from the system + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + Private->Handle, + &gEfiGraphicsOutputProtocolGuid, + &Private->GraphicsOutput, + &gEfiSimpleTextInProtocolGuid, + &Private->SimpleTextIn, + NULL + ); + if (!EFI_ERROR (Status)) { + // + // Shutdown the hardware + // + Status = WinNtGopDestructor (Private); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + gBS->CloseProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + // + // Free our instance data + // + FreeUnicodeStringTable (Private->ControllerNameTable); + + FreePool (Private); + + } + + return Status; +} + + +/** + Convert a unicode string to a UINTN + + @param String Unicode string. + + @return UINTN of the number represented by String. + +**/ +UINTN +Atoi ( + CHAR16 *String + ) +{ + UINTN Number; + CHAR16 *Str; + + // + // skip preceeding white space + // + Str = String; + while ((*Str) && (*Str == ' ' || *Str == '"')) { + Str++; + } + + // + // Convert ot a Number + // + Number = 0; + while (*Str != '\0') { + if ((*Str >= '0') && (*Str <= '9')) { + Number = (Number * 10) +*Str - '0'; + } else { + break; + } + + Str++; + } + + return Number; +} diff --git a/Nt32Pkg/WinNtGopDxe/WinNtGopInput.c b/Nt32Pkg/WinNtGopDxe/WinNtGopInput.c new file mode 100644 index 0000000000..a604dad4e5 --- /dev/null +++ b/Nt32Pkg/WinNtGopDxe/WinNtGopInput.c @@ -0,0 +1,377 @@ +/** @file + +Copyright (c) 2006, 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: + + WinNtGopInput.c + +Abstract: + + This file produces the Simple Text In for an Gop window. + + This stuff is linked at the hip to the Window, since the window + processing is done in a thread kicked off in WinNtGopImplementation.c + + Since the window information is processed in an other thread we need + a keyboard Queue to pass data about. The Simple Text In code just + takes data off the Queue. The WinProc message loop takes keyboard input + and places it in the Queue. + + +**/ + +// +// The package level header files this module uses +// +#include +#include +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +#include +#include +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include + +#include "WinNtGop.h" + + +/** + TODO: Add function description + + @param Private TODO: add argument description + + @retval EFI_SUCCESS TODO: Add description for return value + +**/ +EFI_STATUS +GopPrivateCreateQ ( + IN GOP_PRIVATE_DATA *Private + ) +{ + Private->WinNtThunk->InitializeCriticalSection (&Private->QCriticalSection); + + Private->Queue.Front = 0; + Private->Queue.Rear = MAX_Q - 1; + Private->Queue.Count = 0; + return EFI_SUCCESS; +} + + +/** + TODO: Add function description + + @param Private TODO: add argument description + + @retval EFI_SUCCESS TODO: Add description for return value + +**/ +EFI_STATUS +GopPrivateDestroyQ ( + IN GOP_PRIVATE_DATA *Private + ) +{ + Private->Queue.Count = 0; + Private->WinNtThunk->DeleteCriticalSection (&Private->QCriticalSection); + return EFI_SUCCESS; +} + + +/** + TODO: Add function description + + @param Private TODO: add argument description + @param Key TODO: add argument description + + @retval EFI_NOT_READY TODO: Add description for return value + @retval EFI_SUCCESS TODO: Add description for return value + +**/ +EFI_STATUS +GopPrivateAddQ ( + IN GOP_PRIVATE_DATA *Private, + IN EFI_INPUT_KEY Key + ) +{ + Private->WinNtThunk->EnterCriticalSection (&Private->QCriticalSection); + + if (Private->Queue.Count == MAX_Q) { + Private->WinNtThunk->LeaveCriticalSection (&Private->QCriticalSection); + return EFI_NOT_READY; + } + + Private->Queue.Rear = (Private->Queue.Rear + 1) % MAX_Q; + Private->Queue.Q[Private->Queue.Rear] = Key; + Private->Queue.Count++; + + Private->WinNtThunk->LeaveCriticalSection (&Private->QCriticalSection); + return EFI_SUCCESS; +} + + +/** + TODO: Add function description + + @param Private TODO: add argument description + @param Key TODO: add argument description + + @retval EFI_NOT_READY TODO: Add description for return value + @retval EFI_SUCCESS TODO: Add description for return value + +**/ +EFI_STATUS +GopPrivateDeleteQ ( + IN GOP_PRIVATE_DATA *Private, + OUT EFI_INPUT_KEY *Key + ) +{ + Private->WinNtThunk->EnterCriticalSection (&Private->QCriticalSection); + + if (Private->Queue.Count == 0) { + Private->WinNtThunk->LeaveCriticalSection (&Private->QCriticalSection); + return EFI_NOT_READY; + } + + *Key = Private->Queue.Q[Private->Queue.Front]; + Private->Queue.Front = (Private->Queue.Front + 1) % MAX_Q; + Private->Queue.Count--; + + Private->WinNtThunk->LeaveCriticalSection (&Private->QCriticalSection); + return EFI_SUCCESS; +} + + +/** + TODO: Add function description + + @param Private TODO: add argument description + + @retval EFI_NOT_READY TODO: Add description for return value + @retval EFI_SUCCESS TODO: Add description for return value + +**/ +EFI_STATUS +GopPrivateCheckQ ( + IN GOP_PRIVATE_DATA *Private + ) +{ + if (Private->Queue.Count == 0) { + return EFI_NOT_READY; + } + + return EFI_SUCCESS; +} + +// +// Simple Text In implementation. +// + + +/** + TODO: Add function description + + @param This TODO: add argument description + @param ExtendedVerification TODO: add argument description + + @retval EFI_SUCCESS TODO: Add description for return value + +**/ +EFI_STATUS +EFIAPI +WinNtGopSimpleTextInReset ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + GOP_PRIVATE_DATA *Private; + EFI_INPUT_KEY Key; + EFI_TPL OldTpl; + + Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This); + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // A reset is draining the Queue + // + while (GopPrivateDeleteQ (Private, &Key) == EFI_SUCCESS) + ; + + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + return EFI_SUCCESS; +} + + +/** + TODO: Add function description + + @param This TODO: add argument description + @param Key TODO: add argument description + + @return TODO: add return values + +**/ +STATIC +EFI_STATUS +EFIAPI +WinNtGopSimpleTextInReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +{ + GOP_PRIVATE_DATA *Private; + EFI_STATUS Status; + EFI_TPL OldTpl; + + Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This); + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + Status = GopPrivateCheckQ (Private); + if (!EFI_ERROR (Status)) { + // + // If a Key press exists try and read it. + // + Status = GopPrivateDeleteQ (Private, Key); + } + + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + + return Status; +} + + +/** + TODO: Add function description + + @param Event TODO: add argument description + @param Context TODO: add argument description + + @return TODO: add return values + +**/ +STATIC +VOID +EFIAPI +WinNtGopSimpleTextInWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + GOP_PRIVATE_DATA *Private; + EFI_STATUS Status; + EFI_TPL OldTpl; + + Private = (GOP_PRIVATE_DATA *) Context; + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + Status = GopPrivateCheckQ (Private); + if (!EFI_ERROR (Status)) { + // + // If a there is a key in the queue signal our event. + // + gBS->SignalEvent (Event); + } else { + // + // We need to sleep or NT will schedule this thread with such high + // priority that WinProc thread will never run and we will not see + // keyboard input. This Sleep makes the syste run 10x faster, so don't + // remove it. + // + Private->WinNtThunk->Sleep (1); + } + + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); +} + + +/** + TODO: Add function description + + @param Private TODO: add argument description + + @return TODO: add return values + +**/ +EFI_STATUS +WinNtGopInitializeSimpleTextInForWindow ( + IN GOP_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + + GopPrivateCreateQ (Private); + + // + // Initialize Simple Text In protoocol + // + Private->SimpleTextIn.Reset = WinNtGopSimpleTextInReset; + Private->SimpleTextIn.ReadKeyStroke = WinNtGopSimpleTextInReadKeyStroke; + + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + WinNtGopSimpleTextInWaitForKey, + Private, + &Private->SimpleTextIn.WaitForKey + ); + + return Status; +} + + +/** + TODO: Add function description + + @param Private TODO: add argument description + + @retval EFI_SUCCESS TODO: Add description for return value + +**/ +EFI_STATUS +WinNtGopDestroySimpleTextInForWindow ( + IN GOP_PRIVATE_DATA *Private + ) +{ + GopPrivateDestroyQ (Private); + return EFI_SUCCESS; +} diff --git a/Nt32Pkg/WinNtGopDxe/WinNtGopScreen.c b/Nt32Pkg/WinNtGopDxe/WinNtGopScreen.c new file mode 100644 index 0000000000..e027071228 --- /dev/null +++ b/Nt32Pkg/WinNtGopDxe/WinNtGopScreen.c @@ -0,0 +1,1020 @@ +/** @file + +Copyright (c) 2006 - 2007, 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 EFI 1.1 driver model. + This file just does graphics. + + +**/ +// +// The package level header files this module uses +// +#include +#include +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +#include +#include +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include + +#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. +static 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 + ); + +STATIC +VOID +EFIAPI +KillNtGopThread ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +// +// 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 = PixelBlueGreenRedReserved8BitPerColor; + (*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; + } + + if (ModeNumber == This->Mode->Mode) { + return EFI_SUCCESS; + } + + 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 + // + case WM_SYSKEYDOWN: + Key.ScanCode = 0; + switch (wParam) { + case VK_F10: + Key.ScanCode = SCAN_F10; + Key.UnicodeChar = 0; + GopPrivateAddQ (Private, Key); + return 0; + } + break; + + case WM_KEYDOWN: + Key.ScanCode = 0; + 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; + } + + if (Key.ScanCode != 0) { + Key.UnicodeChar = 0; + GopPrivateAddQ (Private, Key); + } + + 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; + ATOM Atom; + 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. + // + Atom = 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, + &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->CreateEvent ( + EVT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_CALLBACK, + KillNtGopThread, + Private, + &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) 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 + ) +{ + UINT32 UnregisterReturn; + + 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; + + UnregisterReturn = 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. + +**/ +STATIC +VOID +EFIAPI +KillNtGopThread ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + Status = WinNtGopDestructor (Context); +}