aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorHeinrich Schuchardt2018-09-11 15:38:12 -0500
committerAlexander Graf2018-09-23 14:55:30 -0500
commit4fdcf0664842b6e289f1421d1a68e8797da5e4ef (patch)
tree4b474ce3b7eccb24ca3b38dc33959c7dfb17ab64 /lib
parent4f17d8d391f2ba2b5d2496cb1c2c451fd786a53b (diff)
downloadu-boot-4fdcf0664842b6e289f1421d1a68e8797da5e4ef.tar.gz
u-boot-4fdcf0664842b6e289f1421d1a68e8797da5e4ef.tar.xz
u-boot-4fdcf0664842b6e289f1421d1a68e8797da5e4ef.zip
efi_loader: implement key notify functions
Implement registering and unregistreing key notify functions in the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL. Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'lib')
-rw-r--r--lib/efi_loader/efi_console.c101
1 files changed, 98 insertions, 3 deletions
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index a6fd93d2c5..73f7ecf919 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -392,8 +392,23 @@ struct efi_simple_text_output_protocol efi_con_out = {
392 .mode = (void*)&efi_con_mode, 392 .mode = (void*)&efi_con_mode,
393}; 393};
394 394
395/**
396 * struct efi_cin_notify_function - registered console input notify function
397 *
398 * @link: link to list
399 * @data: key to notify
400 * @function: function to call
401 */
402struct efi_cin_notify_function {
403 struct list_head link;
404 struct efi_key_data key;
405 efi_status_t (EFIAPI *function)
406 (struct efi_key_data *key_data);
407};
408
395static bool key_available; 409static bool key_available;
396static struct efi_key_data next_key; 410static struct efi_key_data next_key;
411static LIST_HEAD(cin_notify_functions);
397 412
398/** 413/**
399 * set_shift_mask() - set shift mask 414 * set_shift_mask() - set shift mask
@@ -598,6 +613,34 @@ static efi_status_t efi_cin_read_key(struct efi_key_data *key)
598} 613}
599 614
600/** 615/**
616 * efi_cin_notify() - notify registered functions
617 */
618static void efi_cin_notify(void)
619{
620 struct efi_cin_notify_function *item;
621
622 list_for_each_entry(item, &cin_notify_functions, link) {
623 bool match = true;
624
625 /* We do not support toggle states */
626 if (item->key.key.unicode_char || item->key.key.scan_code) {
627 if (item->key.key.unicode_char !=
628 next_key.key.unicode_char ||
629 item->key.key.scan_code != next_key.key.scan_code)
630 match = false;
631 }
632 if (item->key.key_state.key_shift_state &&
633 item->key.key_state.key_shift_state !=
634 next_key.key_state.key_shift_state)
635 match = false;
636
637 if (match)
638 /* We don't bother about the return code */
639 EFI_CALL(item->function(&next_key));
640 }
641}
642
643/**
601 * efi_cin_check() - check if keyboard input is available 644 * efi_cin_check() - check if keyboard input is available
602 */ 645 */
603static void efi_cin_check(void) 646static void efi_cin_check(void)
@@ -614,8 +657,12 @@ static void efi_cin_check(void)
614 if (ret == EFI_SUCCESS) { 657 if (ret == EFI_SUCCESS) {
615 key_available = true; 658 key_available = true;
616 659
660 /* Notify registered functions */
661 efi_cin_notify();
662
617 /* Queue the wait for key event */ 663 /* Queue the wait for key event */
618 efi_signal_event(efi_con_in.wait_for_key, true); 664 if (key_available)
665 efi_signal_event(efi_con_in.wait_for_key, true);
619 } 666 }
620 } 667 }
621} 668}
@@ -757,9 +804,35 @@ static efi_status_t EFIAPI efi_cin_register_key_notify(
757 struct efi_key_data *key_data), 804 struct efi_key_data *key_data),
758 void **notify_handle) 805 void **notify_handle)
759{ 806{
807 efi_status_t ret = EFI_SUCCESS;
808 struct efi_cin_notify_function *notify_function;
809
760 EFI_ENTRY("%p, %p, %p, %p", 810 EFI_ENTRY("%p, %p, %p, %p",
761 this, key_data, key_notify_function, notify_handle); 811 this, key_data, key_notify_function, notify_handle);
762 return EFI_EXIT(EFI_OUT_OF_RESOURCES); 812
813 /* Check parameters */
814 if (!this || !key_data || !key_notify_function || !notify_handle) {
815 ret = EFI_INVALID_PARAMETER;
816 goto out;
817 }
818
819 EFI_PRINT("u+%04x, sc %04x, sh %08x, tg %02x\n",
820 key_data->key.unicode_char,
821 key_data->key.scan_code,
822 key_data->key_state.key_shift_state,
823 key_data->key_state.key_toggle_state);
824
825 notify_function = calloc(1, sizeof(struct efi_cin_notify_function));
826 if (!notify_function) {
827 ret = EFI_OUT_OF_RESOURCES;
828 goto out;
829 }
830 notify_function->key = *key_data;
831 notify_function->function = key_notify_function;
832 list_add_tail(&notify_function->link, &cin_notify_functions);
833 *notify_handle = notify_function;
834out:
835 return EFI_EXIT(ret);
763} 836}
764 837
765/** 838/**
@@ -779,8 +852,30 @@ static efi_status_t EFIAPI efi_cin_unregister_key_notify(
779 struct efi_simple_text_input_ex_protocol *this, 852 struct efi_simple_text_input_ex_protocol *this,
780 void *notification_handle) 853 void *notification_handle)
781{ 854{
855 efi_status_t ret = EFI_INVALID_PARAMETER;
856 struct efi_cin_notify_function *item, *notify_function =
857 notification_handle;
858
782 EFI_ENTRY("%p, %p", this, notification_handle); 859 EFI_ENTRY("%p, %p", this, notification_handle);
783 return EFI_EXIT(EFI_INVALID_PARAMETER); 860
861 /* Check parameters */
862 if (!this || !notification_handle)
863 goto out;
864
865 list_for_each_entry(item, &cin_notify_functions, link) {
866 if (item == notify_function) {
867 ret = EFI_SUCCESS;
868 break;
869 }
870 }
871 if (ret != EFI_SUCCESS)
872 goto out;
873
874 /* Remove the notify function */
875 list_del(&notify_function->link);
876 free(notify_function);
877out:
878 return EFI_EXIT(ret);
784} 879}
785 880
786 881