diff options
author | Heinrich Schuchardt | 2018-09-11 15:38:12 -0500 |
---|---|---|
committer | Alexander Graf | 2018-09-23 14:55:30 -0500 |
commit | 4fdcf0664842b6e289f1421d1a68e8797da5e4ef (patch) | |
tree | 4b474ce3b7eccb24ca3b38dc33959c7dfb17ab64 /lib | |
parent | 4f17d8d391f2ba2b5d2496cb1c2c451fd786a53b (diff) | |
download | u-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.c | 101 |
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 | */ | ||
402 | struct 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 | |||
395 | static bool key_available; | 409 | static bool key_available; |
396 | static struct efi_key_data next_key; | 410 | static struct efi_key_data next_key; |
411 | static 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 | */ | ||
618 | static 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 | */ |
603 | static void efi_cin_check(void) | 646 | static 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(¬ify_function->link, &cin_notify_functions); | ||
833 | *notify_handle = notify_function; | ||
834 | out: | ||
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(¬ify_function->link); | ||
876 | free(notify_function); | ||
877 | out: | ||
878 | return EFI_EXIT(ret); | ||
784 | } | 879 | } |
785 | 880 | ||
786 | 881 | ||