/** @file Copyright (C) 2005 - 2015, Apple Inc. All rights reserved.
This program and the accompanying materials have not been licensed. Neither is its usage, its redistribution, in source or binary form, licensed, nor implicitely or explicitely permitted, except when required by applicable law. Unless required by applicable law or agreed to in writing, software distributed is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. **/ #include #include #include #include #include #include #include #include #include "AppleKeyAggregator.h" extern EFI_GUID gAppleEventProtocolGuid; STATIC APPLE_EVENT_PROTOCOL mAppleEventProtocol = { 1, NULL, NULL, NULL, NULL, NULL }; // KeyMapGetKeyStrokesByIndex APPLE_KEY_STROKES_INFO * KeyMapGetKeyStrokesByIndex ( IN LIST_ENTRY *List, IN UINTN Index ) // sub_459 { APPLE_KEY_STROKES_INFO *KeyStrokesInfo; KeyStrokesInfo = APPLE_KEY_STROKES_INFO_FROM_LIST_ENTRY(GetFirstNode(List)); while (KeyStrokesInfo->Hdr.Index != Index) { if (IsNull(List, &KeyStrokesInfo->Hdr.This)) { KeyStrokesInfo = NULL; break; } KeyStrokesInfo = APPLE_KEY_STROKES_INFO_FROM_LIST_ENTRY(GetNextNode(List, &KeyStrokesInfo->Hdr.This)); } return KeyStrokesInfo; } // KeyMapBubbleSort VOID KeyMapBubbleSort ( IN OUT UINT16 *Operand, IN UINTN NoChilds ) // sub_72C { UINTN NoRemainingChilds; UINTN Index; UINTN NoRemainingChilds2; UINT16 *OperandPtr; UINT16 FirstChild; if (!Operand || !NoChilds) { return; } if (Operand != NULL) { ++Operand; NoRemainingChilds = (NoChilds - 1); Index = 1; do { NoRemainingChilds2 = NoRemainingChilds; OperandPtr = Operand; if (Index < NoChilds) { do { FirstChild = Operand[-1]; if (FirstChild > *OperandPtr) { Operand[-1] = *OperandPtr; *OperandPtr = FirstChild; } ++OperandPtr; --NoRemainingChilds2; } while (NoRemainingChilds2 > 0); } ++Index; ++Operand; } while ((NoRemainingChilds--) > 0); } } EFI_STATUS EFIAPI KeyMapCreateKeyStrokesBuffer ( IN APPLE_KEY_MAP_DATABASE_PROTOCOL *This, IN UINTN KeyBufferSize, OUT UINTN *Index ) { EFI_STATUS Status; APPLE_KEY_MAP_AGGREGATOR *Aggregator; UINTN BufferSize; APPLE_KEY *Memory; APPLE_KEY_STROKES_INFO *KeyStrokesInfo; if (!This || !Index) { return EFI_INVALID_PARAMETER; } Aggregator = APPLE_KEY_MAP_AGGREGATOR_PRIVATE_FROM_DATABASE (This); if (Aggregator->KeyBuffer != NULL) { gBS->FreePool ((VOID *)Aggregator->KeyBuffer); } BufferSize = (Aggregator->KeyBuffersSize + KeyBufferSize); Aggregator->KeyBuffersSize = BufferSize; Memory = AllocateZeroPool (BufferSize); Aggregator->KeyBuffer = Memory; Status = EFI_OUT_OF_RESOURCES; if (Memory != NULL) { KeyStrokesInfo = AllocateZeroPool (sizeof (APPLE_KEY_STROKES_INFO) + (KeyBufferSize * sizeof (APPLE_KEY))); Status = EFI_OUT_OF_RESOURCES; if (KeyStrokesInfo != NULL) { KeyStrokesInfo->Hdr.Signature = APPLE_KEY_STROKES_INFO_SIGNATURE; KeyStrokesInfo->Hdr.KeyBufferSize = KeyBufferSize; KeyStrokesInfo->Hdr.Index = Aggregator->NextKeyStrokeIndex; ++Aggregator->NextKeyStrokeIndex; InsertTailList (&Aggregator->KeyStrokesInfoList, &KeyStrokesInfo->Hdr.This); Status = EFI_SUCCESS; *Index = KeyStrokesInfo->Hdr.Index; } } return Status; } EFI_STATUS EFIAPI KeyMapRemoveKeyStrokesBuffer ( IN APPLE_KEY_MAP_DATABASE_PROTOCOL *This, IN UINTN Index ) { EFI_STATUS Status; APPLE_KEY_MAP_AGGREGATOR *Aggregator; APPLE_KEY_STROKES_INFO *KeyStrokesInfo; if (!This) { return EFI_INVALID_PARAMETER; } Aggregator = APPLE_KEY_MAP_AGGREGATOR_PRIVATE_FROM_DATABASE (This); KeyStrokesInfo = KeyMapGetKeyStrokesByIndex (&Aggregator->KeyStrokesInfoList, Index); Status = EFI_NOT_FOUND; if (KeyStrokesInfo != NULL) { Aggregator->KeyBuffersSize -= KeyStrokesInfo->Hdr.KeyBufferSize; RemoveEntryList (&KeyStrokesInfo->Hdr.This); gBS->FreePool ((VOID *)KeyStrokesInfo); Status = EFI_SUCCESS; } return Status; } //->SetKeyStrokeBufferKeys => Index=3000, Modifiers=0, NoKeys=0, Keys={5518, 0}, Status=Success EFI_STATUS EFIAPI KeyMapSetKeyStrokeBufferKeys ( IN APPLE_KEY_MAP_DATABASE_PROTOCOL *This, IN UINTN Index, IN APPLE_MODIFIER_MAP Modifiers, IN UINTN NumberOfKeys, IN APPLE_KEY *Keys ) { EFI_STATUS Status; APPLE_KEY_MAP_AGGREGATOR *Aggregator; APPLE_KEY_STROKES_INFO *KeyStrokesInfo; if (!This || !Keys) { return EFI_INVALID_PARAMETER; } Aggregator = APPLE_KEY_MAP_AGGREGATOR_PRIVATE_FROM_DATABASE (This); KeyStrokesInfo = KeyMapGetKeyStrokesByIndex (&Aggregator->KeyStrokesInfoList, Index); Status = EFI_NOT_FOUND; if (KeyStrokesInfo != NULL) { Status = EFI_OUT_OF_RESOURCES; if (KeyStrokesInfo->Hdr.KeyBufferSize >= NumberOfKeys) { KeyStrokesInfo->Hdr.NumberOfKeys = NumberOfKeys; KeyStrokesInfo->Hdr.Modifiers = Modifiers; CopyMem((VOID *)&KeyStrokesInfo->Keys, (VOID *)Keys, (NumberOfKeys * sizeof(APPLE_KEY))); Status = EFI_SUCCESS; } } return Status; } //->ReadKeyState(), count=1, flags=0x0 states={7028,0}, status=Success EFI_STATUS EFIAPI ReadKeyState (APPLE_KEY_STATE_PROTOCOL* This, OUT UINT16 *ModifyFlags, OUT UINTN *PressedKeyCount, OUT APPLE_KEY *Keys) { EFI_STATUS Status; APPLE_KEY_MAP_AGGREGATOR *Aggregator; APPLE_KEY_STROKES_INFO *KeyStrokesInfo; APPLE_MODIFIER_MAP DbModifiers; BOOLEAN Result; UINTN DbNoKeyStrokes; UINTN Index; UINTN Index2; APPLE_KEY Key; if (!This || !ModifyFlags || !PressedKeyCount) { return EFI_INVALID_PARAMETER; } Aggregator = APPLE_KEY_MAP_AGGREGATOR_PRIVATE_FROM_AGGREGATOR (This); KeyStrokesInfo = APPLE_KEY_STROKES_INFO_FROM_LIST_ENTRY (GetFirstNode (&Aggregator->KeyStrokesInfoList)); Result = IsNull (&Aggregator->KeyStrokesInfoList, &KeyStrokesInfo->Hdr.This); if (Result) { *PressedKeyCount = 0; DbNoKeyStrokes = 0; DbModifiers = 0; } else { DbModifiers = 0; DbNoKeyStrokes = 0; do { DbModifiers |= KeyStrokesInfo->Hdr.Modifiers; if (KeyStrokesInfo->Hdr.NumberOfKeys > 0) { Index = 0; do { Key = (&KeyStrokesInfo->Keys)[Index]; ++Index; for (Index2 = 0; Index2 < DbNoKeyStrokes; ++Index2) { if (Aggregator->KeyBuffer[Index2] == Key) { break; } } if (DbNoKeyStrokes == Index2) { Aggregator->KeyBuffer[DbNoKeyStrokes] = Key; ++DbNoKeyStrokes; } } while (Index < KeyStrokesInfo->Hdr.NumberOfKeys); } KeyStrokesInfo = APPLE_KEY_STROKES_INFO_FROM_LIST_ENTRY ( GetNextNode (&Aggregator->KeyStrokesInfoList, &KeyStrokesInfo->Hdr.This) ); Result = IsNull(&Aggregator->KeyStrokesInfoList, &KeyStrokesInfo->Hdr.This); } while (!Result); Result = (DbNoKeyStrokes > *PressedKeyCount); *PressedKeyCount = DbNoKeyStrokes; Status = EFI_BUFFER_TOO_SMALL; if (Result) { return Status; } } *ModifyFlags = DbModifiers; *PressedKeyCount = DbNoKeyStrokes; Status = EFI_SUCCESS; if (Keys != NULL) { gBS->CopyMem((VOID *)Keys, (VOID *)Aggregator->KeyBuffer, (DbNoKeyStrokes * sizeof(APPLE_KEY))); } return Status; } #define DB_KEYS_NUM 8 EFI_STATUS EFIAPI SearchKeyStroke (APPLE_KEY_STATE_PROTOCOL* This, IN UINT16 ModifyFlags, IN UINTN PressedKeyCount, IN OUT APPLE_KEY *Keys, IN BOOLEAN ExactMatch) { EFI_STATUS Status; UINTN DbNoKeys; APPLE_KEY DbKeys[DB_KEYS_NUM]; APPLE_MODIFIER_MAP DbModifiers; INTN Result; UINTN Index; UINTN DbIndex; if (!This || !Keys) { return EFI_INVALID_PARAMETER; } if (!PressedKeyCount) { return EFI_NOT_FOUND; } DbNoKeys = DB_KEYS_NUM; Status = This->ReadKeyState(This, &DbModifiers, &DbNoKeys, DbKeys); if (!EFI_ERROR (Status)) { if (ExactMatch) { Status = EFI_NOT_FOUND; if ((DbModifiers == ModifyFlags) && (DbNoKeys == PressedKeyCount)) { KeyMapBubbleSort ((UINT16 *)Keys, PressedKeyCount); KeyMapBubbleSort ((UINT16 *)DbKeys, DbNoKeys); Result = CompareMem ((VOID *)Keys, (VOID *)DbKeys, (PressedKeyCount * sizeof (APPLE_KEY))); if (Result == 0) { Status = EFI_SUCCESS; } } } else { Status = EFI_NOT_FOUND; if ((DbModifiers & ModifyFlags) == ModifyFlags) { for (Index = 0; Index < PressedKeyCount; ++Index) { for (DbIndex = 0; DbIndex < DbNoKeys; ++DbIndex) { if (Keys[Index] == DbKeys[DbIndex]) { break; } } if (DbNoKeys == DbIndex) { break; } Status = EFI_SUCCESS; } } } } return Status; } // AggregatorEntryPoint /** @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 EFI_ALREADY_STARTED The protocol has already been installed. **/ EFI_STATUS EFIAPI AggregatorEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) // start { EFI_STATUS Status; UINTN NumberHandles; EFI_HANDLE *Buffer; APPLE_KEY_MAP_AGGREGATOR *Aggregator; EFI_HANDLE Handle; Status = gBS->LocateHandleBuffer ( ByProtocol, &gAppleKeyMapDatabaseProtocolGuid, NULL, &NumberHandles, &Buffer ); if (!EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; if (Buffer != NULL) { gBS->FreePool ((VOID *)Buffer); } } else { Aggregator = AllocateZeroPool(sizeof(APPLE_KEY_MAP_AGGREGATOR)); Aggregator->Signature = APPLE_KEY_MAP_AGGREGATOR_SIGNATURE; Aggregator->NextKeyStrokeIndex = 3000; Aggregator->DatabaseProtocol.Revision = APPLE_KEY_MAP_PROTOCOLS_REVISION; Aggregator->DatabaseProtocol.CreateKeyStrokesBuffer = KeyMapCreateKeyStrokesBuffer; Aggregator->DatabaseProtocol.RemoveKeyStrokesBuffer = KeyMapRemoveKeyStrokesBuffer; Aggregator->DatabaseProtocol.SetKeyStrokeBufferKeys = KeyMapSetKeyStrokeBufferKeys; Aggregator->AggregatorProtocol.Signature = APPLE_KEY_MAP_PROTOCOLS_REVISION; Aggregator->AggregatorProtocol.ReadKeyState = ReadKeyState; Aggregator->AggregatorProtocol.SearchKeyStroke = SearchKeyStroke; InitializeListHead (&Aggregator->KeyStrokesInfoList); Handle = NULL; Status = gBS->InstallMultipleProtocolInterfaces ( &Handle, &gAppleKeyMapDatabaseProtocolGuid, (VOID *)&Aggregator->DatabaseProtocol, &gAppleKeyStateProtocolGuid, (VOID *)&Aggregator->AggregatorProtocol, &gAppleEventProtocolGuid, &mAppleEventProtocol, NULL ); /* if (!EFI_ERROR (Status)) { Status = gBS->InstallProtocolInterface(ImageHandle, &gAppleEventProtocolGuid, EFI_NATIVE_INTERFACE, &mAppleEventProtocol); } */ } return Status; }