OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OcAppleKeyMapLib.c
Go to the documentation of this file.
1
19#include <AppleMacEfi.h>
23#include <Library/BaseLib.h>
24#include <Library/BaseMemoryLib.h>
25#include <Library/DebugLib.h>
26#include <Library/MemoryAllocationLib.h>
28#include <Library/OcMiscLib.h>
29#include <Library/OcTimerLib.h>
30#include <Library/TimerLib.h>
31#include <Library/UefiBootServicesTableLib.h>
32
33// KEY_MAP_AGGREGATOR_DATA_SIGNATURE
34#define KEY_MAP_AGGREGATOR_DATA_SIGNATURE \
35 SIGNATURE_32 ('K', 'e', 'y', 'A')
36
37// KEY_MAP_AGGREGATOR_DATA_FROM_AGGREGATOR_THIS
38#define KEY_MAP_AGGREGATOR_DATA_FROM_AGGREGATOR_THIS(This) \
39 CR ( \
40 (This), \
41 KEY_MAP_AGGREGATOR_DATA, \
42 Aggregator, \
43 KEY_MAP_AGGREGATOR_DATA_SIGNATURE \
44 )
45
46// KEY_MAP_AGGREGATOR_DATA_FROM_DATABASE_THIS
47#define KEY_MAP_AGGREGATOR_DATA_FROM_DATABASE_THIS(This) \
48 CR ( \
49 (This), \
50 KEY_MAP_AGGREGATOR_DATA, \
51 Database, \
52 KEY_MAP_AGGREGATOR_DATA_SIGNATURE \
53 )
54
55// KEY_MAP_AGGREGATOR_DATA
65
66// APPLE_KEY_STROKES_INFO_SIGNATURE
67#define APPLE_KEY_STROKES_INFO_SIGNATURE SIGNATURE_32 ('K', 'e', 'y', 'S')
68
69// APPLE_KEY_STROKES_INFO_FROM_LIST_ENTRY
70#define APPLE_KEY_STROKES_INFO_FROM_LIST_ENTRY(Entry) \
71 CR ( \
72 (Entry), \
73 APPLE_KEY_STROKES_INFO, \
74 Link, \
75 APPLE_KEY_STROKES_INFO_SIGNATURE \
76 )
77
78#define SIZE_OF_APPLE_KEY_STROKES_INFO \
79 OFFSET_OF (APPLE_KEY_STROKES_INFO, KeyCodes)
80
81// APPLE_KEY_STROKES_INFO
91
92// InternalGetKeyStrokesByIndex
93STATIC
96 IN KEY_MAP_AGGREGATOR_DATA *KeyMapAggregatorData,
97 IN UINTN Index
98 )
99{
100 APPLE_KEY_STROKES_INFO *KeyStrokesInfo;
101
102 LIST_ENTRY *Entry;
103 APPLE_KEY_STROKES_INFO *KeyStrokesInfoWalker;
104
105 KeyStrokesInfo = NULL;
106
107 for (
108 Entry = GetFirstNode (&KeyMapAggregatorData->KeyStrokesInfoList);
109 !IsNull (&KeyMapAggregatorData->KeyStrokesInfoList, Entry);
110 Entry = GetNextNode (&KeyMapAggregatorData->KeyStrokesInfoList, Entry)
111 )
112 {
113 KeyStrokesInfoWalker = APPLE_KEY_STROKES_INFO_FROM_LIST_ENTRY (Entry);
114
115 if (KeyStrokesInfoWalker->Index == Index) {
116 KeyStrokesInfo = KeyStrokesInfoWalker;
117
118 break;
119 }
120 }
121
122 return KeyStrokesInfo;
123}
124
125// InternalGetKeyStrokes
126
146STATIC
147EFI_STATUS
148EFIAPI
151 OUT APPLE_MODIFIER_MAP *Modifiers,
152 IN OUT UINTN *NumberOfKeyCodes,
153 OUT APPLE_KEY_CODE *KeyCodes OPTIONAL
154 )
155{
156 EFI_STATUS Status;
157
158 KEY_MAP_AGGREGATOR_DATA *KeyMapAggregatorData;
159 LIST_ENTRY *Entry;
160 APPLE_KEY_STROKES_INFO *KeyStrokesInfo;
161 BOOLEAN Result;
162 APPLE_MODIFIER_MAP DbModifiers;
163 UINTN DbNumberOfKeyCodestrokes;
164 UINTN Index;
165 UINTN Index2;
166 APPLE_KEY_CODE Key;
167
168 KeyMapAggregatorData = KEY_MAP_AGGREGATOR_DATA_FROM_AGGREGATOR_THIS (This);
169
170 DbModifiers = 0;
171 DbNumberOfKeyCodestrokes = 0;
172
173 for (
174 Entry = GetFirstNode (&KeyMapAggregatorData->KeyStrokesInfoList);
175 !IsNull (&KeyMapAggregatorData->KeyStrokesInfoList, Entry);
176 Entry = GetNextNode (&KeyMapAggregatorData->KeyStrokesInfoList, Entry)
177 )
178 {
179 KeyStrokesInfo = APPLE_KEY_STROKES_INFO_FROM_LIST_ENTRY (Entry);
180
181 DbModifiers |= KeyStrokesInfo->Modifiers;
182
183 for (Index = 0; Index < KeyStrokesInfo->NumberOfKeyCodes; ++Index) {
184 Key = KeyStrokesInfo->KeyCodes[Index];
185
186 for (Index2 = 0; Index2 < DbNumberOfKeyCodestrokes; ++Index2) {
187 if (KeyMapAggregatorData->KeyCodeBuffer[Index2] == Key) {
188 break;
189 }
190 }
191
192 if (Index2 == DbNumberOfKeyCodestrokes) {
193 KeyMapAggregatorData->KeyCodeBuffer[DbNumberOfKeyCodestrokes] = Key;
194 ++DbNumberOfKeyCodestrokes;
195 }
196 }
197 }
198
199 Result = (BOOLEAN)(DbNumberOfKeyCodestrokes > *NumberOfKeyCodes);
200
201 *NumberOfKeyCodes = DbNumberOfKeyCodestrokes;
202
203 Status = EFI_BUFFER_TOO_SMALL;
204
205 if (!Result) {
206 *Modifiers = DbModifiers;
207
208 Status = EFI_SUCCESS;
209
210 if (KeyCodes != NULL) {
211 CopyMem (
212 (VOID *)KeyCodes,
213 (VOID *)KeyMapAggregatorData->KeyCodeBuffer,
214 (DbNumberOfKeyCodestrokes * sizeof (*KeyCodes))
215 );
216 }
217 }
218
219 return Status;
220}
221
222BOOLEAN
224 IN CONST APPLE_KEY_CODE *Keys,
225 IN UINTN NumKeys,
226 IN CONST APPLE_KEY_CODE *CheckKeys,
227 IN UINTN NumCheckKeys,
228 IN BOOLEAN ExactMatch
229 )
230{
231 UINTN CheckIndex;
232 UINTN Index;
233
234 if (ExactMatch && (NumKeys != NumCheckKeys)) {
235 return FALSE;
236 }
237
238 for (CheckIndex = 0; CheckIndex < NumCheckKeys; ++CheckIndex) {
239 for (Index = 0; Index < NumKeys; ++Index) {
240 if (CheckKeys[CheckIndex] == Keys[Index]) {
241 break;
242 }
243 }
244
245 if (NumKeys == Index) {
246 return FALSE;
247 }
248 }
249
250 return TRUE;
251}
252
253BOOLEAN
255 IN CONST APPLE_KEY_CODE *Keys,
256 IN UINTN NumKeys,
257 IN CONST APPLE_KEY_CODE KeyCode
258 )
259{
260 return OcKeyMapHasKeys (Keys, NumKeys, &KeyCode, 1, FALSE);
261}
262
263VOID
266 IN APPLE_KEY_CODE Key,
267 IN BOOLEAN FlushConsole
268 )
269{
270 EFI_STATUS Status;
271 UINTN NumKeys;
272 APPLE_MODIFIER_MAP Modifiers;
274
275 ASSERT (KeyMap != NULL);
276
277 //
278 // Key flush support for use on systems with EFI driver level key repeat; on newer
279 // and Apple hardware, will hang until all keys (including control keys) come up.
280 //
281 while (TRUE) {
282 NumKeys = ARRAY_SIZE (Keys);
283 Status = KeyMap->GetKeyStrokes (
284 KeyMap,
285 &Modifiers,
286 &NumKeys,
287 Keys
288 );
289
290 if (EFI_ERROR (Status)) {
291 DEBUG ((DEBUG_ERROR, "OCKM: GetKeyStrokes failure - %r\n", Status));
292 break;
293 }
294
295 if ((Key != 0) && !OcKeyMapHasKey (Keys, NumKeys, Key) && (Modifiers == 0)) {
296 break;
297 }
298
299 if ((Key == 0) && (NumKeys == 0) && (Modifiers == 0)) {
300 break;
301 }
302
304 }
305
306 if (FlushConsole) {
308 }
309}
310
311// InternalContainsKeyStrokes
312
329STATIC
330EFI_STATUS
331EFIAPI
334 IN APPLE_MODIFIER_MAP Modifiers,
335 IN UINTN NumberOfKeyCodes,
336 IN OUT APPLE_KEY_CODE *KeyCodes,
337 IN BOOLEAN ExactMatch
338 )
339{
340 EFI_STATUS Status;
341 BOOLEAN Result;
342
343 UINTN DbNumberOfKeyCodes;
344 APPLE_MODIFIER_MAP DbModifiers;
345 APPLE_KEY_CODE DbKeyCodes[8];
346
347 DbNumberOfKeyCodes = ARRAY_SIZE (DbKeyCodes);
348 Status = This->GetKeyStrokes (
349 This,
350 &DbModifiers,
351 &DbNumberOfKeyCodes,
352 DbKeyCodes
353 );
354
355 if (EFI_ERROR (Status)) {
356 return Status;
357 }
358
359 if (ExactMatch) {
360 if (DbModifiers != Modifiers) {
361 return FALSE;
362 }
363 } else if ((DbModifiers & Modifiers) != Modifiers) {
364 return FALSE;
365 }
366
367 Result = OcKeyMapHasKeys (
368 DbKeyCodes,
369 DbNumberOfKeyCodes,
370 KeyCodes,
371 NumberOfKeyCodes,
372 ExactMatch
373 );
374 if (!Result) {
375 return EFI_NOT_FOUND;
376 }
377
378 return EFI_SUCCESS;
379}
380
381// KeyMapCreateKeyStrokesBuffer
382
397STATIC
398EFI_STATUS
399EFIAPI
402 IN UINTN BufferLength,
403 OUT UINTN *Index
404 )
405{
406 EFI_STATUS Status;
407
408 KEY_MAP_AGGREGATOR_DATA *KeyMapAggregatorData;
409 UINTN TotalBufferLength;
411 APPLE_KEY_STROKES_INFO *KeyStrokesInfo;
412
413 KeyMapAggregatorData = KEY_MAP_AGGREGATOR_DATA_FROM_DATABASE_THIS (This);
414
415 if (KeyMapAggregatorData->KeyCodeBuffer != NULL) {
416 gBS->FreePool ((VOID *)KeyMapAggregatorData->KeyCodeBuffer);
417 }
418
419 TotalBufferLength = (KeyMapAggregatorData->KeyCodeBufferLength + BufferLength);
420
421 KeyMapAggregatorData->KeyCodeBufferLength = TotalBufferLength;
422
423 Buffer = AllocateZeroPool (TotalBufferLength * sizeof (*Buffer));
424
425 KeyMapAggregatorData->KeyCodeBuffer = Buffer;
426
427 Status = EFI_OUT_OF_RESOURCES;
428
429 if (Buffer != NULL) {
430 KeyStrokesInfo = AllocateZeroPool (
432 + (BufferLength * sizeof (*Buffer))
433 );
434
435 Status = EFI_OUT_OF_RESOURCES;
436
437 if (KeyStrokesInfo != NULL) {
439 KeyStrokesInfo->KeyCodeBufferLength = BufferLength;
440 KeyStrokesInfo->Index = KeyMapAggregatorData->NextKeyStrokeIndex++;
441
442 InsertTailList (
443 &KeyMapAggregatorData->KeyStrokesInfoList,
444 &KeyStrokesInfo->Link
445 );
446
447 Status = EFI_SUCCESS;
448
449 *Index = KeyStrokesInfo->Index;
450 }
451 }
452
453 return Status;
454}
455
456// KeyMapRemoveKeyStrokesBuffer
457
468STATIC
469EFI_STATUS
470EFIAPI
473 IN UINTN Index
474 )
475{
476 EFI_STATUS Status;
477
478 KEY_MAP_AGGREGATOR_DATA *KeyMapAggregatorData;
479 APPLE_KEY_STROKES_INFO *KeyStrokesInfo;
480
481 KeyMapAggregatorData = KEY_MAP_AGGREGATOR_DATA_FROM_DATABASE_THIS (This);
482
483 KeyStrokesInfo = InternalGetKeyStrokesByIndex (
484 KeyMapAggregatorData,
485 Index
486 );
487
488 Status = EFI_NOT_FOUND;
489
490 if (KeyStrokesInfo != NULL) {
491 KeyMapAggregatorData->KeyCodeBufferLength -= KeyStrokesInfo->KeyCodeBufferLength;
492
493 RemoveEntryList (&KeyStrokesInfo->Link);
494 gBS->FreePool ((VOID *)KeyStrokesInfo);
495
496 Status = EFI_SUCCESS;
497 }
498
499 return Status;
500}
501
502// KeyMapSetKeyStrokeBufferKeys
503
522STATIC
523EFI_STATUS
524EFIAPI
527 IN UINTN Index,
528 IN APPLE_MODIFIER_MAP Modifiers,
529 IN UINTN NumberOfKeyCodes,
530 IN APPLE_KEY_CODE *KeyCodes
531 )
532{
533 EFI_STATUS Status;
534
535 KEY_MAP_AGGREGATOR_DATA *KeyMapAggregatorData;
536 APPLE_KEY_STROKES_INFO *KeyStrokesInfo;
537
538 KeyMapAggregatorData = KEY_MAP_AGGREGATOR_DATA_FROM_DATABASE_THIS (This);
539
540 KeyStrokesInfo = InternalGetKeyStrokesByIndex (
541 KeyMapAggregatorData,
542 Index
543 );
544
545 Status = EFI_NOT_FOUND;
546
547 if (KeyStrokesInfo != NULL) {
548 Status = EFI_OUT_OF_RESOURCES;
549
550 if (KeyStrokesInfo->KeyCodeBufferLength >= NumberOfKeyCodes) {
551 KeyStrokesInfo->NumberOfKeyCodes = NumberOfKeyCodes;
552 KeyStrokesInfo->Modifiers = Modifiers;
553
554 CopyMem (
555 (VOID *)&KeyStrokesInfo->KeyCodes[0],
556 (VOID *)KeyCodes,
557 (NumberOfKeyCodes * sizeof (*KeyCodes))
558 );
559
560 Status = EFI_SUCCESS;
561 }
562 }
563
564 return Status;
565}
566
568
576 VOID
577 )
578{
579 return mKeyMapDatabase;
580}
581
591 IN BOOLEAN Reinstall
592 )
593{
594 EFI_STATUS Status;
595 EFI_STATUS Status2;
596 KEY_MAP_AGGREGATOR_DATA *KeyMapAggregatorData;
599 EFI_HANDLE NewHandle;
600
601 if (Reinstall) {
604 if (EFI_ERROR (Status) || EFI_ERROR (Status2)) {
605 DEBUG ((DEBUG_ERROR, "OCKM: Uninstall failed - %r/%r\n", Status, Status2));
606 return NULL;
607 }
608 } else {
609 Status = gBS->LocateProtocol (
611 NULL,
612 (VOID *)&Database
613 );
614 Status2 = gBS->LocateProtocol (
616 NULL,
617 (VOID *)&Aggregator
618 );
619
620 if (!EFI_ERROR (Status2)) {
621 //
622 // VMware Fusion has no KeyMapDatabase, and it is intended.
623 //
624 if (!EFI_ERROR (Status)) {
625 mKeyMapDatabase = Database;
626 }
627
628 return Aggregator;
629 } else if (!EFI_ERROR (Status)) {
630 //
631 // Installed KeyMapDatabase makes no sense, however.
632 //
633 return NULL;
634 }
635 }
636
637 KeyMapAggregatorData = AllocateZeroPool (sizeof (*KeyMapAggregatorData));
638
639 if (KeyMapAggregatorData == NULL) {
640 return NULL;
641 }
642
643 KeyMapAggregatorData->Signature = KEY_MAP_AGGREGATOR_DATA_SIGNATURE;
644 KeyMapAggregatorData->NextKeyStrokeIndex = 3000;
645
650
652 KeyMapAggregatorData->Aggregator.GetKeyStrokes = InternalGetKeyStrokes;
654
655 InitializeListHead (&KeyMapAggregatorData->KeyStrokesInfoList);
656
657 NewHandle = NULL;
658 Status = gBS->InstallMultipleProtocolInterfaces (
659 &NewHandle,
661 (VOID *)&KeyMapAggregatorData->Database,
663 (VOID *)&KeyMapAggregatorData->Aggregator,
664 NULL
665 );
666 if (EFI_ERROR (Status)) {
667 FreePool (KeyMapAggregatorData);
668 return NULL;
669 }
670
671 mKeyMapDatabase = &KeyMapAggregatorData->Database;
672 return &KeyMapAggregatorData->Aggregator;
673}
APPLE_HID_USAGE APPLE_KEY_CODE
Definition AppleHid.h:317
UINT16 APPLE_MODIFIER_MAP
Definition AppleHid.h:102
#define APPLE_KEY_MAP_AGGREGATOR_PROTOCOL_REVISION
EFI_GUID gAppleKeyMapAggregatorProtocolGuid
#define APPLE_KEY_MAP_DATABASE_PROTOCOL_REVISION
EFI_GUID gAppleKeyMapDatabaseProtocolGuid
#define ARRAY_SIZE(Array)
Definition AppleMacEfi.h:34
APPLE_KEY_MAP_AGGREGATOR_PROTOCOL * OcAppleKeyMapInstallProtocols(IN BOOLEAN Reinstall)
VOID OcKeyMapFlush(IN APPLE_KEY_MAP_AGGREGATOR_PROTOCOL *KeyMap, IN APPLE_KEY_CODE Key, IN BOOLEAN FlushConsole)
STATIC EFI_STATUS EFIAPI InternalRemoveKeyStrokesBuffer(IN APPLE_KEY_MAP_DATABASE_PROTOCOL *This, IN UINTN Index)
BOOLEAN OcKeyMapHasKeys(IN CONST APPLE_KEY_CODE *Keys, IN UINTN NumKeys, IN CONST APPLE_KEY_CODE *CheckKeys, IN UINTN NumCheckKeys, IN BOOLEAN ExactMatch)
STATIC EFI_STATUS EFIAPI InternalGetKeyStrokes(IN APPLE_KEY_MAP_AGGREGATOR_PROTOCOL *This, OUT APPLE_MODIFIER_MAP *Modifiers, IN OUT UINTN *NumberOfKeyCodes, OUT APPLE_KEY_CODE *KeyCodes OPTIONAL)
STATIC EFI_STATUS EFIAPI InternalSetKeyStrokeBufferKeys(IN APPLE_KEY_MAP_DATABASE_PROTOCOL *This, IN UINTN Index, IN APPLE_MODIFIER_MAP Modifiers, IN UINTN NumberOfKeyCodes, IN APPLE_KEY_CODE *KeyCodes)
STATIC APPLE_KEY_STROKES_INFO * InternalGetKeyStrokesByIndex(IN KEY_MAP_AGGREGATOR_DATA *KeyMapAggregatorData, IN UINTN Index)
#define KEY_MAP_AGGREGATOR_DATA_SIGNATURE
#define KEY_MAP_AGGREGATOR_DATA_FROM_DATABASE_THIS(This)
APPLE_KEY_MAP_DATABASE_PROTOCOL * OcAppleKeyMapGetDatabase(VOID)
STATIC APPLE_KEY_MAP_DATABASE_PROTOCOL * mKeyMapDatabase
STATIC EFI_STATUS EFIAPI InternalCreateKeyStrokesBuffer(IN APPLE_KEY_MAP_DATABASE_PROTOCOL *This, IN UINTN BufferLength, OUT UINTN *Index)
#define SIZE_OF_APPLE_KEY_STROKES_INFO
BOOLEAN OcKeyMapHasKey(IN CONST APPLE_KEY_CODE *Keys, IN UINTN NumKeys, IN CONST APPLE_KEY_CODE KeyCode)
#define APPLE_KEY_STROKES_INFO_SIGNATURE
#define KEY_MAP_AGGREGATOR_DATA_FROM_AGGREGATOR_THIS(This)
#define APPLE_KEY_STROKES_INFO_FROM_LIST_ENTRY(Entry)
STATIC EFI_STATUS EFIAPI InternalContainsKeyStrokes(IN APPLE_KEY_MAP_AGGREGATOR_PROTOCOL *This, IN APPLE_MODIFIER_MAP Modifiers, IN UINTN NumberOfKeyCodes, IN OUT APPLE_KEY_CODE *KeyCodes, IN BOOLEAN ExactMatch)
#define OC_KEY_MAP_DEFAULT_SIZE
EFI_BOOT_SERVICES * gBS
EFI_STATUS OcUninstallAllProtocolInstances(EFI_GUID *Protocol)
VOID OcConsoleFlush(VOID)
#define OC_MINIMAL_CPU_DELAY
Definition OcTimerLib.h:15
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
Definition OcTypingLib.h:42
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
#define ASSERT(x)
Definition coder.h:55
KEY_MAP_CONTAINS_KEY_STROKES ContainsKeyStrokes
KEY_MAP_CREATE_KEY_STROKES_BUFFER CreateKeyStrokesBuffer
KEY_MAP_REMOVE_KEY_STROKES_BUFFER RemoveKeyStrokesBuffer
KEY_MAP_SET_KEY_STROKES_KEYS SetKeyStrokeBufferKeys
APPLE_KEY_CODE KeyCodes[]
APPLE_MODIFIER_MAP Modifiers
APPLE_KEY_MAP_DATABASE_PROTOCOL Database
APPLE_KEY_CODE * KeyCodeBuffer
APPLE_KEY_MAP_AGGREGATOR_PROTOCOL Aggregator