/* * SimpleTextProxy.h * * Created by Jief on 25 May 2018. * */ #include #include #include #include #include #include #include #include #include #include #include #include "AppleKeyMapUtils.h" #include "SimpleTextExProxy.h" // DBG_TO: 0=no debug, 1=serial, 2=console 3=log // serial requires // [PcdsFixedAtBuild] // gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x07 // gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xFFFFFFFF // in package DSC file #ifdef JIEF_DEBUG #define DBG_APPLEKEYFEEDER 2 #endif #if DBG_APPLEKEYFEEDER == 3 #define DBG(...) MemLog(FALSE, 0, __VA_ARGS__) #elif DBG_APPLEKEYFEEDER == 2 #define DBG(...) AsciiPrint(__VA_ARGS__) #elif DBG_APPLEKEYFEEDER == 1 #define DBG(...) DebugPrint(1, __VA_ARGS__) #else #define DBG(...) #endif static EFI_HANDLE OriginalConsoleInHandle; static EFI_SIMPLE_TEXT_INPUT_PROTOCOL* OriginalSimpleText; EFI_SIMPLE_TEXT_INPUT_PROTOCOL AppleKeyFeederSimpleTextProxy; /** 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 SimpleTextProxyReset)( IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, IN BOOLEAN ExtendedVerification ) { DBG("SimpleTextProxyReset\n"); return OriginalSimpleText->Reset(OriginalSimpleText, ExtendedVerification); } /* * Buffer for EFI_INPUT_KEY */ static EFI_INPUT_KEY KeyDataBuffer[32]; // size must be a power of 2 #define KEYDATABUFFER_SIZE_MINUS_ONE ( ( sizeof(KeyDataBuffer) / sizeof(KeyDataBuffer[0]) ) - 1 ) static UINTN KeyDataBufferIndexStart = 0; static UINTN KeyDataBufferIndexEnd = 0; /** 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 SimpleTextProxyReadKeyStroke( IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, OUT EFI_INPUT_KEY *Key ) { //DBG("SimpleTextProxyReadKeyStroke\n"); if ( AppleKeyFeederSimpleTextExProxy.ReadKeyStrokeEx ) { EFI_KEY_DATA KeyData; EFI_STATUS Status = SimpleTextExProxyReadKeyStroke(&AppleKeyFeederSimpleTextExProxy, &KeyData); if ( EFI_ERROR(Status) ) { return Status; } *Key = KeyData.Key; } else { if ( KeyDataBufferIndexStart == KeyDataBufferIndexEnd ) { return EFI_NOT_READY; //DBG("SimpleTextProxyReadKeyStroke: returns EFI_NOT_READY (%x)\n", EFI_NOT_READY); } *Key = KeyDataBuffer[KeyDataBufferIndexStart]; //DBG("SimpleTextProxyReadKeyStroke before KeyDataBufferIndexStart=%d, KeyDataBufferIndexEnd=%d\n", KeyDataBufferIndexStart, KeyDataBufferIndexEnd); KeyDataBufferIndexStart = (KeyDataBufferIndexStart + 1) & KEYDATABUFFER_SIZE_MINUS_ONE; } return EFI_SUCCESS; } /* * Buffering keys */ VOID EFIAPI SimpleTextProxyBufferKeyStroke ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_STATUS Status; //DBG("SimpleTextProxyBufferKeyStroke\n"); EFI_INPUT_KEY key; Status = OriginalSimpleText->ReadKeyStroke(OriginalSimpleText, &key); if (EFI_ERROR(Status) ) { //DBG("SimpleTextProxyBufferKeyStroke ReadKeyStroke failed, Status=%x\n", Status); }else{ DBG("SimpleTextProxyBufferKeyStroke ReadKey key ScanCode=%x, UnicodeChar=%x, KeyDataBufferIndexStart=%d, KeyDataBufferIndexEnd=%d\n", key.ScanCode, key.UnicodeChar, KeyDataBufferIndexStart, KeyDataBufferIndexEnd); KeyDataBuffer[KeyDataBufferIndexEnd] = key; // if key are not consumed, and buffer is full, the buffer will be lost. // That happens at Apple preboot env which doesn't use ConIn. But at preboot env, we don't care about key stored in buffer. KeyDataBufferIndexEnd = (KeyDataBufferIndexEnd + 1) & KEYDATABUFFER_SIZE_MINUS_ONE; gBS->SignalEvent(Event); EFI_KEY_DATA KeyData; KeyData.Key.ScanCode = key.ScanCode; KeyData.Key.UnicodeChar = key.UnicodeChar; KeyData.KeyState.KeyShiftState = KeyData.KeyState.KeyToggleState = 0; SendDataToAppleMap(&KeyData); } return; } /* * */ VOID EFIAPI WaitForKeyEvent ( IN EFI_EVENT Event, IN VOID *Context ) { DBG("WaitForKeyEvent\n"); if ( KeyDataBufferIndexStart != KeyDataBufferIndexEnd ) { gBS->SignalEvent (Event); } } /**************************************************************** * Entry point ***************************************************************/ EFI_STATUS EFIAPI SimpleTextProxyInit( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { DBG("SimpleTextProxyInit\n"); EFI_STATUS Status = EFI_SUCCESS; OriginalConsoleInHandle = SystemTable->ConsoleInHandle; OriginalSimpleText = SystemTable->ConIn; AppleKeyFeederSimpleTextProxy.Reset = SimpleTextProxyReset; AppleKeyFeederSimpleTextProxy.ReadKeyStroke = SimpleTextProxyReadKeyStroke; Status = SimpleTextExProxyInit(ImageHandle, SystemTable); if ( EFI_ERROR (Status) ) { DBG("SimpleTextProxyInit: CreateEvent2 failed, Status=%x\n", Status); } SystemTable->ConsoleInHandle = ImageHandle; SystemTable->ConIn = &AppleKeyFeederSimpleTextProxy; gST->ConIn = &AppleKeyFeederSimpleTextProxy; DBG("SimpleTextProxyInit returns %x\n", Status); return Status; }