From 2ff79f2eda16f8219140d3dae188d2b341f610e1 Mon Sep 17 00:00:00 2001 From: andrewfish Date: Tue, 30 Nov 2010 23:38:40 +0000 Subject: Adding Simple Pointer, GOP, SimpleTextInEx, and Networking protocols to the emulator. Cleaned up POSIX include situation by centralizing it in a single file, like NT32. Fixed TPL issue with TPL High not being emulated correctly, it was possible to take a timer tick when the locks in the DXE core should have prevented this. Remove some unused files to make things easier to maintain. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11105 6f19259b-4bc3-4df7-8a09-765794883524 --- UnixPkg/UnixGopDxe/ComponentName.c | 251 +++++++++++ UnixPkg/UnixGopDxe/UnixGop.h | 377 ++++++++++++++++ UnixPkg/UnixGopDxe/UnixGop.inf | 73 +++ UnixPkg/UnixGopDxe/UnixGopDriver.c | 396 +++++++++++++++++ UnixPkg/UnixGopDxe/UnixGopInput.c | 885 +++++++++++++++++++++++++++++++++++++ UnixPkg/UnixGopDxe/UnixGopScreen.c | 404 +++++++++++++++++ 6 files changed, 2386 insertions(+) create mode 100644 UnixPkg/UnixGopDxe/ComponentName.c create mode 100644 UnixPkg/UnixGopDxe/UnixGop.h create mode 100644 UnixPkg/UnixGopDxe/UnixGop.inf create mode 100644 UnixPkg/UnixGopDxe/UnixGopDriver.c create mode 100644 UnixPkg/UnixGopDxe/UnixGopInput.c create mode 100644 UnixPkg/UnixGopDxe/UnixGopScreen.c (limited to 'UnixPkg/UnixGopDxe') diff --git a/UnixPkg/UnixGopDxe/ComponentName.c b/UnixPkg/UnixGopDxe/ComponentName.c new file mode 100644 index 0000000000..e57e85d159 --- /dev/null +++ b/UnixPkg/UnixGopDxe/ComponentName.c @@ -0,0 +1,251 @@ +/*++ + +Copyright (c) 2006, Intel Corporation. All rights reserved.
+Portions copyright (c) 2010, Apple, Inc. 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: + +--*/ + +#include "UnixGop.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +UnixGopComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +UnixGopComponentNameGetControllerName ( + 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 gUnixGopComponentName = { + UnixGopComponentNameGetDriverName, + UnixGopComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gUnixGopComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) UnixGopComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) UnixGopComponentNameGetControllerName, + "en" +}; + + +EFI_UNICODE_STRING_TABLE mUnixGopDriverNameTable[] = { + { "eng", L"Unix GOP Driver" }, + { NULL , NULL } +}; + + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name 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. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] 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 +UnixGopComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mUnixGopDriverNameTable, + DriverName, + (BOOLEAN)(This == &gUnixGopComponentName) + ); +} + + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] 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[in] 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[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name 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. Language is specified in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] 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 +UnixGopComponentNameGetControllerName ( + 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, + gUnixGopDriverBinding.DriverBindingHandle, + &gEfiUnixIoProtocolGuid + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + // + // Get our context back + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiGraphicsOutputProtocolGuid, + (VOID **)&GraphicsOutput, + gUnixGopDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Private = GOP_PRIVATE_DATA_FROM_THIS (GraphicsOutput); + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + Private->ControllerNameTable, + ControllerName, + (BOOLEAN)(This == &gUnixGopComponentName) + ); + +} diff --git a/UnixPkg/UnixGopDxe/UnixGop.h b/UnixPkg/UnixGopDxe/UnixGop.h new file mode 100644 index 0000000000..16232e5446 --- /dev/null +++ b/UnixPkg/UnixGopDxe/UnixGop.h @@ -0,0 +1,377 @@ +/*++ + +Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+Portions copyright (c) 2010, Apple, Inc. 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: + + UnixGop.h + +Abstract: + + Private data for the Gop driver that is bound to the Unix Thunk protocol + +--*/ + +#ifndef _UNIX_UGA_H_ +#define _UNIX_UGA_H_ + +#include +#include "UnixDxe.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "Protocol/UnixUgaIo.h" + +#include + + + +#define MAX_Q 256 + +typedef struct { + UINTN Front; + UINTN Rear; + UINTN Count; + EFI_INPUT_KEY Q[MAX_Q]; +} GOP_QUEUE_FIXED; + +#define UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE SIGNATURE_32 ('U', 'g', 'S', 'n') +typedef struct _UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY { + UINTN Signature; + EFI_HANDLE NotifyHandle; + EFI_KEY_DATA KeyData; + EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn; + EFI_EVENT Event; + LIST_ENTRY NotifyEntry; +} UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY; + +#define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER 0xffff + +typedef struct { + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + UINT32 ColorDepth; + UINT32 RefreshRate; +} GOP_MODE_DATA; + + + +extern EFI_DRIVER_BINDING_PROTOCOL gUnixGopDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gUnixGopComponentName; + +#define UNIX_UGA_CLASS_NAME L"UnixGopWindow" + +#define GOP_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('G', 'o', 'p', 'N') +typedef struct { + UINT64 Signature; + + EFI_HANDLE Handle; + EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutput; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleTextIn; + EFI_SIMPLE_POINTER_PROTOCOL SimplePointer; + + EFI_UNIX_THUNK_PROTOCOL *UnixThunk; + EFI_UNIX_UGA_IO_PROTOCOL *UgaIo; + + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + + EFI_SIMPLE_POINTER_MODE PointerMode; + // + // GOP Private Data for QueryMode () + // + GOP_MODE_DATA *ModeData; + + + // + // UGA Private Data knowing when to start hardware + // + BOOLEAN HardwareNeedsStarting; + + CHAR16 *WindowName; + + GOP_QUEUE_FIXED Queue; + + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleTextInEx; + EFI_KEY_STATE KeyState; + LIST_ENTRY NotifyList; + + +} 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) + +#define GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS(a) \ + CR(a, GOP_PRIVATE_DATA, SimpleTextInEx, GOP_PRIVATE_DATA_SIGNATURE) + +#define GOP_PRIVATE_DATA_FROM_POINTER_MODE_THIS(a) \ + CR(a, GOP_PRIVATE_DATA, SimplePointer, GOP_PRIVATE_DATA_SIGNATURE) + + +// +// Global Protocol Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gUnixGopDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gUnixGopComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gUnixGopComponentName2; + +// +// Gop Hardware abstraction internal worker functions +// +EFI_STATUS +UnixGopSupported ( + IN EFI_UNIX_IO_PROTOCOL *UnixIo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + UnixIo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +UnixGopConstructor ( + IN GOP_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +UnixGopDestructor ( + IN GOP_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +// +// EFI 1.1 driver model prototypes for Win UNIX UGA +// + +EFI_STATUS +EFIAPI +UnixGopInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ImageHandle - TODO: add argument description + SystemTable - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +UnixGopDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Handle - TODO: add argument description + RemainingDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +UnixGopDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Handle - TODO: add argument description + RemainingDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +UnixGopDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Handle - TODO: add argument description + NumberOfChildren - TODO: add argument description + ChildHandleBuffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +GopPrivateAddQ ( + IN GOP_PRIVATE_DATA *Private, + IN EFI_INPUT_KEY Key + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + Key - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +UnixGopInitializeSimpleTextInForWindow ( + IN GOP_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +UnixGopInitializeSimplePointerForWindow ( + IN GOP_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; +#endif diff --git a/UnixPkg/UnixGopDxe/UnixGop.inf b/UnixPkg/UnixGopDxe/UnixGop.inf new file mode 100644 index 0000000000..1dd33bd2e5 --- /dev/null +++ b/UnixPkg/UnixGopDxe/UnixGop.inf @@ -0,0 +1,73 @@ +## @file +# Uga driver +# +# UGA is short hand for Universal Graphics Abstraction protocol. +# This file is a verision of UgaIo the uses UnixThunk system calls as an IO +# abstraction. For a PCI device UnixIo would be replaced with +# a PCI IO abstraction that abstracted a specific PCI device. +# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2010, Apple, Inc. 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] + INF_VERSION = 0x00010005 + BASE_NAME = UnixUga + FILE_GUID = f33cad86-8985-11db-8040-0040d02b1835 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = InitializeUnixGop + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gUnixUgaDriverBinding +# COMPONENT_NAME = gUnixUgaComponentName +# + +[Sources] + ComponentName.c + UnixGopScreen.c + UnixGopDriver.c + UnixGopInput.c + UnixGop.h + + +[Packages] + MdePkg/MdePkg.dec + UnixPkg/UnixPkg.dec + + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + UefiLib + UefiDriverEntryPoint + BaseLib + DebugLib + + +[Guids] + gEfiEventExitBootServicesGuid # SOMETIMES_CONSUMED Create Event: EVENT_GROUP_GUID + gEfiUnixGopGuid # ALWAYS_CONSUMED + + +[Protocols] + gEfiGraphicsOutputProtocolGuid + gEfiSimpleTextInProtocolGuid # PROTOCOL BY_START + gEfiSimpleTextInputExProtocolGuid # PROTOCOL BY_START + gEfiSimplePointerProtocolGuid # PROTOCOL BY_START + gEfiUnixIoProtocolGuid # PROTOCOL TO_START + diff --git a/UnixPkg/UnixGopDxe/UnixGopDriver.c b/UnixPkg/UnixGopDxe/UnixGopDriver.c new file mode 100644 index 0000000000..dcc79d97f5 --- /dev/null +++ b/UnixPkg/UnixGopDxe/UnixGopDriver.c @@ -0,0 +1,396 @@ +/*++ + +Copyright (c) 2006, Intel Corporation. All rights reserved.
+Portions copyright (c) 2010, Apple, Inc. 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: + + UnixGopDriver.c + +Abstract: + + This file implements the EFI 1.1 Device Driver model requirements for UGA + + UGA is short hand for Universal Graphics Abstraction protocol. + + This file is a verision of UgaIo the uses UnixThunk system calls as an IO + abstraction. For a PCI device UnixIo would be replaced with + a PCI IO abstraction that abstracted a specific PCI device. + +--*/ + +#include "UnixGop.h" + + +EFI_STATUS +FreeNotifyList ( + IN OUT LIST_ENTRY *ListHead + ) +/*++ + +Routine Description: + +Arguments: + + ListHead - The list head + +Returns: + + EFI_SUCCESS - Free the notify list successfully + EFI_INVALID_PARAMETER - ListHead is invalid. + +--*/ +{ + UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY *NotifyNode; + + if (ListHead == NULL) { + return EFI_INVALID_PARAMETER; + } + while (!IsListEmpty (ListHead)) { + NotifyNode = CR ( + ListHead->ForwardLink, + UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY, + NotifyEntry, + UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE + ); + RemoveEntryList (ListHead->ForwardLink); + gBS->FreePool (NotifyNode); + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +UnixGopDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + 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 Status; + EFI_UNIX_IO_PROTOCOL *UnixIo; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiUnixIoProtocolGuid, + (VOID **)&UnixIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = UnixGopSupported (UnixIo); + + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + Handle, + &gEfiUnixIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + return Status; +} + +EFI_STATUS +EFIAPI +UnixGopDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + 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_UNIX_IO_PROTOCOL *UnixIo; + EFI_STATUS Status; + GOP_PRIVATE_DATA *Private; + + // + // Grab the protocols we need + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiUnixIoProtocolGuid, + (VOID **)&UnixIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Allocate Private context data for SGO inteface. + // + Private = NULL; + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (GOP_PRIVATE_DATA), + (VOID **)&Private + ); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Set up context record + // + Private->Signature = GOP_PRIVATE_DATA_SIGNATURE; + Private->Handle = Handle; + Private->UnixThunk = UnixIo->UnixThunk; + + Private->ControllerNameTable = NULL; + + AddUnicodeString ( + "eng", + gUnixGopComponentName.SupportedLanguages, + &Private->ControllerNameTable, + UnixIo->EnvString + ); + AddUnicodeString2 ( + "en", + gUnixGopComponentName2.SupportedLanguages, + &Private->ControllerNameTable, + UnixIo->EnvString, + FALSE + ); + + Private->WindowName = UnixIo->EnvString; + + Status = UnixGopConstructor (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, + &gEfiSimplePointerProtocolGuid, &Private->SimplePointer, +// &gEfiSimpleTextInputExProtocolGuid, &Private->SimpleTextInEx, + NULL + ); + +Done: + if (EFI_ERROR (Status)) { + + gBS->CloseProtocol ( + Handle, + &gEfiUnixIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + if (Private != NULL) { + // + // On Error Free back private data + // + if (Private->ControllerNameTable != NULL) { + FreeUnicodeStringTable (Private->ControllerNameTable); + } + if (Private->SimpleTextIn.WaitForKey != NULL) { + gBS->CloseEvent (Private->SimpleTextIn.WaitForKey); + } + if (Private->SimpleTextInEx.WaitForKeyEx != NULL) { + gBS->CloseEvent (Private->SimpleTextInEx.WaitForKeyEx); + } + FreeNotifyList (&Private->NotifyList); + + gBS->FreePool (Private); + } + } + + return Status; +} + +EFI_STATUS +EFIAPI +UnixGopDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + 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_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_STATUS Status; + GOP_PRIVATE_DATA *Private; + + Status = gBS->OpenProtocol ( + Handle, + &gEfiGraphicsOutputProtocolGuid, + (VOID **)&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, + &gEfiSimplePointerProtocolGuid, &Private->SimplePointer, +// &gEfiSimpleTextInputExProtocolGuid, &Private->SimpleTextInEx, + NULL + ); + if (!EFI_ERROR (Status)) { + // + // Shutdown the hardware + // + Status = UnixGopDestructor (Private); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + gBS->CloseProtocol ( + Handle, + &gEfiUnixIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + // + // Free our instance data + // + FreeUnicodeStringTable (Private->ControllerNameTable); + + Status = gBS->CloseEvent (Private->SimpleTextIn.WaitForKey); + ASSERT_EFI_ERROR (Status); + + Status = gBS->CloseEvent (Private->SimpleTextInEx.WaitForKeyEx); + ASSERT_EFI_ERROR (Status); + + FreeNotifyList (&Private->NotifyList); + + gBS->FreePool (Private); + + } + + return Status; +} + + + + +EFI_DRIVER_BINDING_PROTOCOL gUnixGopDriverBinding = { + UnixGopDriverBindingSupported, + UnixGopDriverBindingStart, + UnixGopDriverBindingStop, + 0xa, + NULL, + NULL +}; + + + +/** + The user Entry Point for module UnixGop. 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 +InitializeUnixGop ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gUnixGopDriverBinding, + ImageHandle, + &gUnixGopComponentName, + &gUnixGopComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + + return Status; +} + diff --git a/UnixPkg/UnixGopDxe/UnixGopInput.c b/UnixPkg/UnixGopDxe/UnixGopInput.c new file mode 100644 index 0000000000..e681fc9ce4 --- /dev/null +++ b/UnixPkg/UnixGopDxe/UnixGopInput.c @@ -0,0 +1,885 @@ +/*++ + +Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+Portions copyright (c) 2010, Apple, Inc. All rights reserved. +Portions copyright (c) 2010, Apple Inc. 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. + + +--*/ + +#include "UnixGop.h" + + +BOOLEAN +GopPrivateIsKeyRegistered ( + IN EFI_KEY_DATA *RegsiteredData, + IN EFI_KEY_DATA *InputData + ) +/*++ + +Routine Description: + +Arguments: + + RegsiteredData - A pointer to a buffer that is filled in with the keystroke + state data for the key that was registered. + InputData - A pointer to a buffer that is filled in with the keystroke + state data for the key that was pressed. + +Returns: + TRUE - Key be pressed matches a registered key. + FLASE - Match failed. + +--*/ +{ + ASSERT (RegsiteredData != NULL && InputData != NULL); + + if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) || + (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) { + return FALSE; + } + + // + // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored. + // + if (RegsiteredData->KeyState.KeyShiftState != 0 && + RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) { + return FALSE; + } + if (RegsiteredData->KeyState.KeyToggleState != 0 && + RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) { + return FALSE; + } + + return TRUE; + +} + + +VOID +EFIAPI +GopPrivateInvokeRegisteredFunction ( + IN VOID *Context, + IN EFI_KEY_DATA *KeyData + ) +{ + LIST_ENTRY *Link; + UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY *CurrentNotify; + GOP_PRIVATE_DATA *Private = (GOP_PRIVATE_DATA *)Context; + + for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR ( + Link, + UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY, + NotifyEntry, + UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE + ); + if (GopPrivateIsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { + // We could be called at a high TPL so signal an event to call the registered function + // at a lower TPL. + gBS->SignalEvent (CurrentNotify->Event); + } + } +} + + + +// +// Simple Text In implementation. +// + +/** + Reset the input device and optionally run diagnostics + + @param This Protocol instance pointer. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset. + +**/ +EFI_STATUS +EFIAPI +UnixGopSimpleTextInReset ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + GOP_PRIVATE_DATA *Private; + EFI_KEY_DATA KeyData; + EFI_TPL OldTpl; + + Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This); + if (Private->UgaIo == NULL) { + return EFI_SUCCESS; + } + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // A reset is draining the Queue + // + while (Private->UgaIo->UgaGetKey (Private->UgaIo, &KeyData) == EFI_SUCCESS) + ; + + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + return EFI_SUCCESS; +} + + +/** + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existence of a keystroke via WaitForEvent () call. + + @param This Protocol instance pointer. + @param Key A pointer to a buffer that is filled in with the keystroke + information for the key that was pressed. + + @retval EFI_SUCCESS The keystroke information was returned. + @retval EFI_NOT_READY There was no keystroke data available. + @retval EFI_DEVICE_ERROR The keystroke information was not returned due to + hardware errors. + +**/ +EFI_STATUS +EFIAPI +UnixGopSimpleTextInReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +{ + GOP_PRIVATE_DATA *Private; + EFI_STATUS Status; + EFI_TPL OldTpl; + EFI_KEY_DATA KeyData; + + Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This); + if (Private->UgaIo == NULL) { + return EFI_NOT_READY; + } + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + Status = Private->UgaIo->UgaGetKey(Private->UgaIo, &KeyData); + CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY)); + + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + + return Status; +} + + + +/** + SimpleTextIn and SimpleTextInEx Notify Wait Event + + @param Event Event whose notification function is being invoked. + @param Context Pointer to GOP_PRIVATE_DATA. + +**/ +VOID +EFIAPI +UnixGopSimpleTextInWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + GOP_PRIVATE_DATA *Private; + EFI_STATUS Status; + EFI_TPL OldTpl; + + Private = (GOP_PRIVATE_DATA *) Context; + if (Private->UgaIo == NULL) { + return; + } + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + Status = Private->UgaIo->UgaCheckKey (Private->UgaIo); + if (!EFI_ERROR (Status)) { + // + // If a there is a key in the queue signal our event. + // + gBS->SignalEvent (Event); + } + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); +} + + +// +// Simple Text Input Ex protocol functions +// + + +/** + The Reset() function resets the input device hardware. As part + of initialization process, the firmware/device will make a quick + but reasonable attempt to verify that the device is functioning. + If the ExtendedVerification flag is TRUE the firmware may take + an extended amount of time to verify the device is operating on + reset. Otherwise the reset operation is to occur as quickly as + possible. The hardware verification process is not defined by + this specification and is left up to the platform firmware or + driver to implement. + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param ExtendedVerification Indicates that the driver may + perform a more exhaustive + verification operation of the + device during reset. + + + @retval EFI_SUCCESS The device was reset. + + @retval EFI_DEVICE_ERROR The device is not functioning + correctly and could not be reset. + +**/ +EFI_STATUS +EFIAPI +UnixGopSimpleTextInExResetEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Reset the input device and optionaly run diagnostics + + Arguments: + This - Protocol instance pointer. + ExtendedVerification - Driver may perform diagnostics on reset. + + Returns: + EFI_SUCCESS - The device was reset. + +--*/ +{ + GOP_PRIVATE_DATA *Private; + + Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This); + + return EFI_SUCCESS; +} + + + +/** + The function reads the next keystroke from the input device. If + there is no pending keystroke the function returns + EFI_NOT_READY. If there is a pending keystroke, then + KeyData.Key.ScanCode is the EFI scan code defined in Error! + Reference source not found. The KeyData.Key.UnicodeChar is the + actual printable character or is zero if the key does not + represent a printable character (control key, function key, + etc.). The KeyData.KeyState is shift state for the character + reflected in KeyData.Key.UnicodeChar or KeyData.Key.ScanCode . + When interpreting the data from this function, it should be + noted that if a class of printable characters that are + normally adjusted by shift modifiers (e.g. Shift Key + "f" + key) would be presented solely as a KeyData.Key.UnicodeChar + without the associated shift state. So in the previous example + of a Shift Key + "f" key being pressed, the only pertinent + data returned would be KeyData.Key.UnicodeChar with the value + of "F". This of course would not typically be the case for + non-printable characters such as the pressing of the Right + Shift Key + F10 key since the corresponding returned data + would be reflected both in the KeyData.KeyState.KeyShiftState + and KeyData.Key.ScanCode values. UEFI drivers which implement + the EFI_SIMPLE_TEXT_INPUT_EX protocol are required to return + KeyData.Key and KeyData.KeyState values. These drivers must + always return the most current state of + KeyData.KeyState.KeyShiftState and + KeyData.KeyState.KeyToggleState. It should also be noted that + certain input devices may not be able to produce shift or toggle + state information, and in those cases the high order bit in the + respective Toggle and Shift state fields should not be active. + + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param KeyData A pointer to a buffer that is filled in with + the keystroke state data for the key that was + pressed. + + + @retval EFI_SUCCESS The keystroke information was + returned. + + @retval EFI_NOT_READY There was no keystroke data available. + EFI_DEVICE_ERROR The keystroke + information was not returned due to + hardware errors. + + +**/ +EFI_STATUS +EFIAPI +UnixGopSimpleTextInExReadKeyStrokeEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData + ) +/*++ + + Routine Description: + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + Arguments: + This - Protocol instance pointer. + KeyData - A pointer to a buffer that is filled in with the keystroke + state data for the key that was pressed. + + Returns: + EFI_SUCCESS - The keystroke information was returned. + EFI_NOT_READY - There was no keystroke data availiable. + EFI_DEVICE_ERROR - The keystroke information was not returned due to + hardware errors. + EFI_INVALID_PARAMETER - KeyData is NULL. + +--*/ +{ + EFI_STATUS Status; + GOP_PRIVATE_DATA *Private; + EFI_TPL OldTpl; + + + if (KeyData == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This); + if (Private->UgaIo == NULL) { + return EFI_NOT_READY; + } + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + Status = Private->UgaIo->UgaGetKey(Private->UgaIo, KeyData); + + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + + return Status; +} + + + +/** + The SetState() function allows the input device hardware to + have state settings adjusted. + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param KeyToggleState Pointer to the EFI_KEY_TOGGLE_STATE to + set the state for the input device. + + + @retval EFI_SUCCESS The device state was set appropriately. + + @retval EFI_DEVICE_ERROR The device is not functioning + correctly and could not have the + setting adjusted. + + @retval EFI_UNSUPPORTED The device does not support the + ability to have its state set. + +**/ +EFI_STATUS +EFIAPI +UnixGopSimpleTextInExSetState ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState + ) +{ + GOP_PRIVATE_DATA *Private; + EFI_STATUS Status; + EFI_TPL OldTpl; + + Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This); + if (Private->UgaIo == NULL) { + return EFI_NOT_READY; + } + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + Status = Private->UgaIo->UgaKeySetState (Private->UgaIo, KeyToggleState); + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + + return Status; +} + + +/** + SimpleTextIn and SimpleTextInEx Notify Wait Event + + @param Event Event whose notification function is being invoked. + @param Context Pointer to GOP_PRIVATE_DATA. + +**/ +VOID +EFIAPI +UnixGopRegisterKeyCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY *ExNotify = (UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY *)Context; + + ExNotify->KeyNotificationFn (&ExNotify->KeyData); +} + + + +/** + The RegisterKeystrokeNotify() function registers a function + which will be called when a specified keystroke will occur. + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param KeyData A pointer to a buffer that is filled in with + the keystroke information for the key that was + pressed. + + @param KeyNotificationFunction Points to the function to be + called when the key sequence + is typed specified by KeyData. + + + @param NotifyHandle Points to the unique handle assigned to + the registered notification. + + @retval EFI_SUCCESS The device state was set + appropriately. + + @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary + data structures. + +**/ +EFI_STATUS +EFIAPI +UnixGopSimpleTextInExRegisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT EFI_HANDLE *NotifyHandle + ) +{ + EFI_STATUS Status; + GOP_PRIVATE_DATA *Private; + UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY *CurrentNotify; + LIST_ENTRY *Link; + UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY *NewNotify; + + if (KeyData == NULL || KeyNotificationFunction == NULL || NotifyHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This); + + // + // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered. + // + for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR ( + Link, + UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY, + NotifyEntry, + UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE + ); + if (GopPrivateIsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { + if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) { + *NotifyHandle = CurrentNotify->NotifyHandle; + return EFI_SUCCESS; + } + } + } + + // + // Allocate resource to save the notification function + // + NewNotify = (UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY *) AllocateZeroPool (sizeof (UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY)); + if (NewNotify == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + NewNotify->Signature = UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE; + NewNotify->KeyNotificationFn = KeyNotificationFunction; + NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify; + CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData)); + InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry); + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + UnixGopRegisterKeyCallback, + NewNotify, + NewNotify->Event + ); + ASSERT_EFI_ERROR (Status); + + + *NotifyHandle = NewNotify->NotifyHandle; + + return EFI_SUCCESS; + +} + + +/** + The UnregisterKeystrokeNotify() function removes the + notification which was previously registered. + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param NotificationHandle The handle of the notification + function being unregistered. + + @retval EFI_SUCCESS The device state was set appropriately. + + @retval EFI_INVALID_PARAMETER The NotificationHandle is + invalid. + +**/ +EFI_STATUS +EFIAPI +UnixGopSimpleTextInExUnregisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_HANDLE NotificationHandle + ) +/*++ + + Routine Description: + Remove a registered notification function from a particular keystroke. + + Arguments: + This - Protocol instance pointer. + NotificationHandle - The handle of the notification function being unregistered. + + Returns: + EFI_SUCCESS - The notification function was unregistered successfully. + EFI_INVALID_PARAMETER - The NotificationHandle is invalid. + +--*/ +{ + GOP_PRIVATE_DATA *Private; + LIST_ENTRY *Link; + UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY *CurrentNotify; + + if (NotificationHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (((UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY *) NotificationHandle)->Signature != UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + + Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This); + + for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = CR ( + Link, + UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY, + NotifyEntry, + UNIX_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE + ); + if (CurrentNotify->NotifyHandle == NotificationHandle) { + // + // Remove the notification function from NotifyList and free resources + // + RemoveEntryList (&CurrentNotify->NotifyEntry); + + gBS->CloseEvent (CurrentNotify->Event); + + gBS->FreePool (CurrentNotify); + return EFI_SUCCESS; + } + } + + // + // Can not find the specified Notification Handle + // + return EFI_INVALID_PARAMETER; +} + + + +/** + Initialize SimplelTextIn and SimpleTextInEx protocols in the Private + context structure. + + @param Private Context structure to fill in. + + @return EFI_SUCCESS Initialization was a success + +**/ +EFI_STATUS +UnixGopInitializeSimpleTextInForWindow ( + IN GOP_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + + // + // Initialize Simple Text In protoocol + // + Private->SimpleTextIn.Reset = UnixGopSimpleTextInReset; + Private->SimpleTextIn.ReadKeyStroke = UnixGopSimpleTextInReadKeyStroke; + + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + UnixGopSimpleTextInWaitForKey, + Private, + &Private->SimpleTextIn.WaitForKey + ); + ASSERT_EFI_ERROR (Status); + + + // + // Initialize Simple Text In Ex + // + + Private->SimpleTextInEx.Reset = UnixGopSimpleTextInExResetEx; + Private->SimpleTextInEx.ReadKeyStrokeEx = UnixGopSimpleTextInExReadKeyStrokeEx; + Private->SimpleTextInEx.SetState = UnixGopSimpleTextInExSetState; + Private->SimpleTextInEx.RegisterKeyNotify = UnixGopSimpleTextInExRegisterKeyNotify; + Private->SimpleTextInEx.UnregisterKeyNotify = UnixGopSimpleTextInExUnregisterKeyNotify; + + Private->SimpleTextInEx.Reset (&Private->SimpleTextInEx, FALSE); + + InitializeListHead (&Private->NotifyList); + + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + UnixGopSimpleTextInWaitForKey, + Private, + &Private->SimpleTextInEx.WaitForKeyEx + ); + ASSERT_EFI_ERROR (Status); + + + return Status; +} + + + + + + + +// +// Simple Pointer implementation. +// + + +/** + Resets the pointer device hardware. + + @param This A pointer to the EFI_SIMPLE_POINTER_PROTOCOL + instance. + @param ExtendedVerification Indicates that the driver may perform a more exhaustive + verification operation of the device during reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset. + +**/ +EFI_STATUS +EFIAPI +UnixGopSimplePointerReset ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + GOP_PRIVATE_DATA *Private; + EFI_SIMPLE_POINTER_STATE State; + EFI_TPL OldTpl; + + Private = GOP_PRIVATE_DATA_FROM_POINTER_MODE_THIS (This); + if (Private->UgaIo == NULL) { + return EFI_SUCCESS; + } + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + // + // A reset is draining the Queue + // + while (Private->UgaIo->UgaGetPointerState (Private->UgaIo, &State) == EFI_SUCCESS) + ; + + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + return EFI_SUCCESS; +} + + +/** + Retrieves the current state of a pointer device. + + @param This A pointer to the EFI_SIMPLE_POINTER_PROTOCOL + instance. + @param State A pointer to the state information on the pointer device. + + @retval EFI_SUCCESS The state of the pointer device was returned in State. + @retval EFI_NOT_READY The state of the pointer device has not changed since the last call to + GetState(). + @retval EFI_DEVICE_ERROR A device error occurred while attempting to retrieve the pointer device's + current state. + +**/ +EFI_STATUS +EFIAPI +UnixGopSimplePointerGetState ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN OUT EFI_SIMPLE_POINTER_STATE *State + ) +{ + GOP_PRIVATE_DATA *Private; + EFI_STATUS Status; + EFI_TPL OldTpl; + + Private = GOP_PRIVATE_DATA_FROM_POINTER_MODE_THIS (This); + if (Private->UgaIo == NULL) { + return EFI_NOT_READY; + } + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + Status = Private->UgaIo->UgaGetPointerState (Private->UgaIo, State); + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + + return Status; +} + + +/** + SimplePointer Notify Wait Event + + @param Event Event whose notification function is being invoked. + @param Context Pointer to GOP_PRIVATE_DATA. + +**/ +VOID +EFIAPI +UnixGopSimplePointerWaitForInput ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + GOP_PRIVATE_DATA *Private; + EFI_STATUS Status; + EFI_TPL OldTpl; + + Private = (GOP_PRIVATE_DATA *) Context; + if (Private->UgaIo == NULL) { + return; + } + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + Status = Private->UgaIo->UgaCheckPointer (Private->UgaIo); + if (!EFI_ERROR (Status)) { + // + // If the pointer state has changed, signal our event. + // + gBS->SignalEvent (Event); + } + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); +} + + +/** + SimplePointer constructor + + @param Private Context structure to fill in. + + @retval EFI_SUCCESS Constructor had success + +**/ +EFI_STATUS +UnixGopInitializeSimplePointerForWindow ( + IN GOP_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + + // + // Initialize Simple Pointer protoocol + // + Private->PointerMode.ResolutionX = 1; + Private->PointerMode.ResolutionY = 1; + Private->PointerMode.ResolutionZ = 1; + Private->PointerMode.LeftButton = TRUE; + Private->PointerMode.RightButton = TRUE; + + Private->SimplePointer.Reset = UnixGopSimplePointerReset; + Private->SimplePointer.GetState = UnixGopSimplePointerGetState; + Private->SimplePointer.Mode = &Private->PointerMode; + + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + UnixGopSimplePointerWaitForInput, + Private, + &Private->SimplePointer.WaitForInput + ); + + return Status; +} diff --git a/UnixPkg/UnixGopDxe/UnixGopScreen.c b/UnixPkg/UnixGopDxe/UnixGopScreen.c new file mode 100644 index 0000000000..943cc83c32 --- /dev/null +++ b/UnixPkg/UnixGopDxe/UnixGopScreen.c @@ -0,0 +1,404 @@ +/*++ + +Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+Portions copyright (c) 2010, Apple, Inc. 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: + + UnixGopScreen.c + +Abstract: + + This file produces the graphics abstration of UGA. It is called by + UnixGopDriver.c file which deals with the EFI 1.1 driver model. + This file just does graphics. + +--*/ + +#include "UnixGop.h" + +EFI_UNIX_THUNK_PROTOCOL *mUnix; +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 +UnixGopStartWindow ( + IN GOP_PRIVATE_DATA *Private, + IN UINT32 HorizontalResolution, + IN UINT32 VerticalResolution, + IN UINT32 ColorDepth, + IN UINT32 RefreshRate + ); + +VOID +EFIAPI +KillUgaGopThread ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +// +// UGA Protocol Member Functions +// + +EFI_STATUS +EFIAPI +UnixGopQuerytMode ( + 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; +} + + + +EFI_STATUS +EFIAPI +UnixGopSetMode ( + 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; + + 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 = UnixGopStartWindow ( + Private, + ModeData->HorizontalResolution, + ModeData->VerticalResolution, + ModeData->ColorDepth, + ModeData->RefreshRate + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Private->HardwareNeedsStarting = FALSE; + } + + + Status = Private->UgaIo->UgaSize( + Private->UgaIo, + ModeData->HorizontalResolution, + ModeData->VerticalResolution + ); + + + Fill.Red = 0x7f; + Fill.Green = 0x7F; + Fill.Blue = 0x7f; + This->Blt ( + This, + &Fill, + EfiBltVideoFill, + 0, + 0, + 0, + 0, + ModeData->HorizontalResolution, + ModeData->VerticalResolution, + ModeData->HorizontalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + return EFI_SUCCESS; +} + + + +EFI_STATUS +EFIAPI +UnixGopBlt ( + 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; + EFI_STATUS Status; + UGA_BLT_ARGS GopBltArgs; + + 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_UGA_PIXEL); + } + + // + // 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); + + // + // Pack UGA Draw protocol parameters to UGA_BLT_ARGS structure to adapt to + // GopBlt() API of Unix UGA IO protocol. + // + GopBltArgs.DestinationX = DestinationX; + GopBltArgs.DestinationY = DestinationY; + GopBltArgs.Height = Height; + GopBltArgs.Width = Width; + GopBltArgs.SourceX = SourceX; + GopBltArgs.SourceY = SourceY; + GopBltArgs.Delta = Delta; + Status = Private->UgaIo->UgaBlt ( + Private->UgaIo, + (EFI_UGA_PIXEL *)BltBuffer, + BltOperation, + &GopBltArgs + ); + + gBS->RestoreTPL (OriginalTPL); + + return Status; +} + + +// +// Construction and Destruction functions +// + +EFI_STATUS +UnixGopSupported ( + IN EFI_UNIX_IO_PROTOCOL *UnixIo + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: UnixIo - 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 +{ + // + // 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 (UnixIo->TypeGuid, &gEfiUnixGopGuid)) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + + +VOID +EFIAPI +GopPrivateInvokeRegisteredFunction ( + IN VOID *Context, + IN EFI_KEY_DATA *KeyData + ); + + +EFI_STATUS +UnixGopStartWindow ( + IN GOP_PRIVATE_DATA *Private, + IN UINT32 HorizontalResolution, + IN UINT32 VerticalResolution, + IN UINT32 ColorDepth, + IN UINT32 RefreshRate + ) +{ + EFI_STATUS Status; + + mUnix = Private->UnixThunk; + + // + // Register to be notified on exit boot services so we can destroy the window. + // + Status = gBS->CreateEvent ( + EVT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_CALLBACK, + KillUgaGopThread, + Private, + &mGopScreenExitBootServicesEvent + ); + + Status = Private->UnixThunk->UgaCreate (&Private->UgaIo, Private->WindowName); + if (!EFI_ERROR (Status)) { + // Register callback to support RegisterKeyNotify() + Status = Private->UgaIo->UgaRegisterKeyNotify (Private->UgaIo, GopPrivateInvokeRegisteredFunction, Private); + ASSERT_EFI_ERROR (Status); + } + return Status; +} + +EFI_STATUS +UnixGopConstructor ( + GOP_PRIVATE_DATA *Private + ) +{ + Private->ModeData = mGopModeData; + + Private->GraphicsOutput.QueryMode = UnixGopQuerytMode; + Private->GraphicsOutput.SetMode = UnixGopSetMode; + Private->GraphicsOutput.Blt = UnixGopBlt; + + // + // 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->UgaIo = NULL; + + UnixGopInitializeSimpleTextInForWindow (Private); + + UnixGopInitializeSimplePointerForWindow (Private); + + return EFI_SUCCESS; +} + + + +EFI_STATUS +UnixGopDestructor ( + GOP_PRIVATE_DATA *Private + ) +{ + if (!Private->HardwareNeedsStarting) { + Private->UgaIo->UgaClose (Private->UgaIo); + Private->UgaIo = NULL; + } + + // + // 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; +} + +VOID +EFIAPI +KillUgaGopThread ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + This is the UGA screen's callback notification function for exit-boot-services. + All we do here is call UnixGopDestructor(). + +Arguments: + + Event - not used + Context - pointer to the Private structure. + +Returns: + + None. + +--*/ +{ + EFI_STATUS Status; + Status = UnixGopDestructor (Context); +} -- cgit v1.2.3