260 lines
6.3 KiB
C

/** @file
AppleEventDxe
Copyright (c) 2018, vit9696
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 <AppleMacEfi.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include "AppleEventInternal.h"
// APPLE_EVENT_QUEUE_SIGNATURE
#define APPLE_EVENT_QUEUE_SIGNATURE SIGNATURE_32 ('A', 'E', 'v', 'Q')
// APPLE_EVENT_QUEUE_FROM_LIST_ENTRY
#define APPLE_EVENT_QUEUE_FROM_LIST_ENTRY(ListEntry) \
CR ((ListEntry), APPLE_EVENT_QUEUE, Link, APPLE_EVENT_QUEUE_SIGNATURE)
// APPLE_EVENT_QUEUE
typedef struct {
UINT32 Signature; ///<
LIST_ENTRY Link; ///<
APPLE_EVENT_INFORMATION *Information; ///<
} APPLE_EVENT_QUEUE;
// mQueueEvent
STATIC EFI_EVENT mQueueEvent = NULL;
// mQueueEventCreated
STATIC BOOLEAN mQueueEventCreated = FALSE;
// mEventQueueList
STATIC LIST_ENTRY mQueue = INITIALIZE_LIST_HEAD_VARIABLE (mQueue);
// mQueueLock
STATIC EFI_LOCK mQueueLock = {
0,
0,
FALSE
};
// InternalSignalAndCloseQueueEvent
VOID
InternalSignalAndCloseQueueEvent (
VOID
)
{
DEBUG ((DEBUG_VERBOSE, "InternalSignalAndCloseQueueEvent\n"));
gBS->SignalEvent (mQueueEvent);
if (mQueueEventCreated && (mQueueEvent != NULL)) {
gBS->CloseEvent (mQueueEvent);
}
}
// InternalQueueEventNotifyFunction
STATIC
VOID
EFIAPI
InternalQueueEventNotifyFunction (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
LIST_ENTRY *EventQueueEntry;
APPLE_EVENT_QUEUE *EventQueue;
DEBUG ((DEBUG_VERBOSE, "InternalQueueEventNotifyFunction\n"));
if (mQueueEventCreated) {
do {
Status = EfiAcquireLockOrFail (&mQueueLock);
} while (EFI_ERROR (Status));
InternalFlagAllEventsReady ();
EventQueueEntry = GetFirstNode (&mQueue);
while (!IsNull (&mQueue, EventQueueEntry)) {
EventQueue = APPLE_EVENT_QUEUE_FROM_LIST_ENTRY (EventQueueEntry);
InternalSignalEvents (EventQueue->Information);
if ( ((EventQueue->Information->EventType & APPLE_ALL_KEYBOARD_EVENTS) != 0)
&& (EventQueue->Information->EventData.KeyData != NULL))
{
FreePool (
(VOID *)EventQueue->Information->EventData.KeyData
);
}
EventQueueEntry = RemoveEntryList (EventQueueEntry);
FreePool ((VOID *)EventQueue->Information);
FreePool ((VOID *)EventQueue);
}
InternalRemoveUnregisteredEvents ();
EfiReleaseLock (&mQueueLock);
}
}
// InternalCreateQueueEvent
VOID
InternalCreateQueueEvent (
VOID
)
{
EFI_STATUS Status;
DEBUG ((DEBUG_VERBOSE, "InternalCreateQueueEvent\n"));
EfiInitializeLock (&mQueueLock, TPL_NOTIFY);
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
InternalQueueEventNotifyFunction,
NULL,
&mQueueEvent
);
if (!EFI_ERROR (Status)) {
mQueueEventCreated = TRUE;
}
}
// EventCreateAppleEventQueueInfo
APPLE_EVENT_INFORMATION *
EventCreateAppleEventQueueInfo (
IN APPLE_EVENT_DATA EventData,
IN APPLE_EVENT_TYPE EventType,
IN DIMENSION *PointerPosition,
IN APPLE_MODIFIER_MAP Modifiers
)
{
APPLE_EVENT_INFORMATION *QueueInfo;
EFI_TIME CreationTime;
DEBUG ((DEBUG_VERBOSE, "EventCreateAppleEventQueueInfo\n"));
QueueInfo = AllocateZeroPool (sizeof (*QueueInfo));
if (QueueInfo != NULL) {
gRT->GetTime (&CreationTime, NULL);
QueueInfo->EventType = EventType;
QueueInfo->EventData = EventData;
QueueInfo->Modifiers = Modifiers;
QueueInfo->CreationTime.Year = CreationTime.Year;
QueueInfo->CreationTime.Month = CreationTime.Month;
QueueInfo->CreationTime.Day = CreationTime.Day;
QueueInfo->CreationTime.Hour = CreationTime.Hour;
QueueInfo->CreationTime.Minute = CreationTime.Minute;
QueueInfo->CreationTime.Second = CreationTime.Second;
QueueInfo->CreationTime.Pad1 = CreationTime.Pad1;
if (PointerPosition != NULL) {
CopyMem (
(VOID *)&QueueInfo->PointerPosition,
(VOID *)PointerPosition,
sizeof (*PointerPosition)
);
}
} else {
DEBUG ((DEBUG_VERBOSE, "EventCreateAppleEventQueueInfo alloc failure\n"));
}
return QueueInfo;
}
// EventAddEventToQueue
VOID
EventAddEventToQueue (
IN APPLE_EVENT_INFORMATION *Information
)
{
EFI_STATUS Status;
APPLE_EVENT_QUEUE *EventQueue;
DEBUG ((DEBUG_VERBOSE, "EventAddEventToQueue\n"));
if (mQueueEventCreated) {
do {
Status = EfiAcquireLockOrFail (&mQueueLock);
} while (EFI_ERROR (Status));
EventQueue = AllocateZeroPool (sizeof (*EventQueue));
if (EventQueue != NULL) {
EventQueue->Signature = APPLE_EVENT_QUEUE_SIGNATURE;
EventQueue->Information = Information;
InsertTailList (&mQueue, &EventQueue->Link);
} else {
DEBUG ((DEBUG_VERBOSE, "EventAddEventToQueue alloc failure\n"));
}
EfiReleaseLock (&mQueueLock);
gBS->SignalEvent (mQueueEvent);
}
}
// EventCreateEventQueue
EFI_STATUS
EventCreateEventQueue (
IN APPLE_EVENT_DATA EventData,
IN APPLE_EVENT_TYPE EventType,
IN APPLE_MODIFIER_MAP Modifiers
)
{
EFI_STATUS Status;
APPLE_EVENT_INFORMATION *Information;
DEBUG ((DEBUG_VERBOSE, "EventCreateEventQueue\n"));
Status = EFI_INVALID_PARAMETER;
if ((EventData.Raw != 0) || (Modifiers != 0)) {
Information = EventCreateAppleEventQueueInfo (
EventData,
EventType,
NULL,
Modifiers
);
Status = EFI_OUT_OF_RESOURCES;
if (Information != NULL) {
EventAddEventToQueue (Information);
Status = EFI_SUCCESS;
} else {
DEBUG ((DEBUG_VERBOSE, "EventCreateEventQueue alloc failure\n"));
}
}
return Status;
}