From a20592ecd18a82a62d84b1a6087ff2e608d633b4 Mon Sep 17 00:00:00 2001 From: A1ive <10670106+a1ive@users.noreply.github.com> Date: Tue, 29 Mar 2022 22:49:37 +0800 Subject: [PATCH] Add mouse support for uefi (#1457) * fix gcc11 warnings * add mouse support for uefi --- .../grub-2.04/grub-core/Makefile.core.def | 6 + GRUB2/MOD_SRC/grub-2.04/grub-core/fs/fshelp.c | 2 +- GRUB2/MOD_SRC/grub-2.04/grub-core/kern/disk.c | 2 +- .../grub-2.04/grub-core/term/efi/mouse.c | 247 ++++++++++++++++++ .../grub-2.04/grub-core/ventoy/ventoy_cmd.c | 2 +- GRUB2/MOD_SRC/grub-2.04/install.sh | 2 +- GRUB2/MOD_SRC/grub-2.04/util/grub-install.c | 1 + 7 files changed, 258 insertions(+), 4 deletions(-) create mode 100644 GRUB2/MOD_SRC/grub-2.04/grub-core/term/efi/mouse.c diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/Makefile.core.def b/GRUB2/MOD_SRC/grub-2.04/grub-core/Makefile.core.def index 987400db..5daba477 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/Makefile.core.def +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/Makefile.core.def @@ -1622,6 +1622,12 @@ module = { common = term/setkey.c; }; +module = { + name = mouse; + efi = term/efi/mouse.c; + enable = efi; +}; + module = { name = hello; common = hello/hello.c; diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/fs/fshelp.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/fs/fshelp.c index f5b6772e..9a98c04b 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/fs/fshelp.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/fs/fshelp.c @@ -426,7 +426,7 @@ grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node, if (grub_errno) return -1; } - else if (read_hook != (grub_disk_read_hook_t)grub_disk_blocklist_read) + else if (read_hook != (void *)grub_disk_blocklist_read) grub_memset (buf, 0, blockend); buf += blocksize - skipfirst; diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/disk.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/disk.c index 04d6ce76..e3da637f 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/disk.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/disk.c @@ -471,7 +471,7 @@ grub_err_t grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_off_t offset, grub_size_t size, void *buf) { - if (disk->read_hook == (grub_disk_read_hook_t)grub_disk_blocklist_read) + if (disk->read_hook == (void *)grub_disk_blocklist_read) { return grub_disk_blocklist_read((ventoy_img_chunk_list *)disk->read_hook_data, sector, size, disk->log_sector_size); } diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/term/efi/mouse.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/term/efi/mouse.c new file mode 100644 index 00000000..c4e3ace5 --- /dev/null +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/term/efi/mouse.c @@ -0,0 +1,247 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2022 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define GRUB_EFI_SIMPLE_POINTER_GUID \ + { 0x31878c87, 0x0b75, 0x11d5, \ + { 0x9a, 0x4f, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +typedef struct +{ + grub_efi_int32_t x; + grub_efi_int32_t y; + grub_efi_int32_t z; + grub_efi_boolean_t left; + grub_efi_boolean_t right; +} grub_efi_mouse_state; + +grub_efi_mouse_state no_move = {0, 0, 0, 0, 0}; + +typedef struct +{ + grub_efi_uint64_t x; + grub_efi_uint64_t y; + grub_efi_uint64_t z; + grub_efi_boolean_t left; + grub_efi_boolean_t right; +} grub_efi_mouse_mode; + +struct grub_efi_simple_pointer_protocol +{ + grub_efi_status_t (*reset) (struct grub_efi_simple_pointer_protocol *this, + grub_efi_boolean_t extended_verification); + grub_efi_status_t (*get_state) (struct grub_efi_simple_pointer_protocol *this, + grub_efi_mouse_state *state); + grub_efi_event_t *wait_for_input; + grub_efi_mouse_mode *mode; +}; +typedef struct grub_efi_simple_pointer_protocol grub_efi_simple_pointer_protocol_t; + +typedef struct +{ + grub_efi_uintn_t count; + grub_efi_simple_pointer_protocol_t **mouse; +} grub_efi_mouse_prot_t; + +static grub_int32_t +mouse_div (grub_int32_t a, grub_uint64_t b) +{ + grub_int32_t s = 1, q, ret; + grub_uint64_t n = a; + if (!b) + return 0; + if (a < 0) + { + s = -1; + n = -a; + } + q = grub_divmod64 (n, b, NULL); + ret = s * (q > 0 ? q : -q); + return ret; +} + +static grub_efi_mouse_prot_t * +grub_efi_mouse_prot_init (void) +{ + grub_efi_status_t status; + grub_efi_guid_t mouse_guid = GRUB_EFI_SIMPLE_POINTER_GUID; + grub_efi_mouse_prot_t *mouse_input = NULL; + grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; + grub_efi_handle_t *buf; + grub_efi_uintn_t count; + grub_efi_uintn_t i; + + status = efi_call_5 (b->locate_handle_buffer, GRUB_EFI_BY_PROTOCOL, + &mouse_guid, NULL, &count, &buf); + if (status != GRUB_EFI_SUCCESS) + { +#ifdef MOUSE_DEBUG + grub_printf ("ERROR: SimplePointerProtocol not found.\n"); +#endif + return NULL; + } + + mouse_input = grub_malloc (sizeof (grub_efi_mouse_prot_t)); + if (!mouse_input) + return NULL; + mouse_input->mouse = grub_malloc (count + * sizeof (grub_efi_simple_pointer_protocol_t *)); + if (!mouse_input->mouse) + { + grub_free (mouse_input); + return NULL; + } + mouse_input->count = count; + for (i = 0; i < count; i++) + { + efi_call_3 (b->handle_protocol, + buf[i], &mouse_guid, (void **)&mouse_input->mouse[i]); +#ifdef MOUSE_DEBUG + grub_printf ("%d %p ", (int)i, mouse_input->mouse[i]); +#endif + efi_call_2 (mouse_input->mouse[i]->reset, mouse_input->mouse[i], 1); +#ifdef MOUSE_DEBUG + grub_printf + ("[%"PRIuGRUB_UINT64_T"] [%"PRIuGRUB_UINT64_T"] [%"PRIuGRUB_UINT64_T"]\n", + mouse_input->mouse[i]->mode->x, + mouse_input->mouse[i]->mode->y, mouse_input->mouse[i]->mode->z); +#endif + } + return mouse_input; +} + +static grub_err_t +grub_efi_mouse_input_init (struct grub_term_input *term) +{ + grub_efi_mouse_prot_t *mouse_input = NULL; + if (term->data) + return 0; + mouse_input = grub_efi_mouse_prot_init (); + if (!mouse_input) + return GRUB_ERR_BAD_OS; + + term->data = (void *)mouse_input; + + return 0; +} + +static int +grub_mouse_getkey (struct grub_term_input *term) +{ + grub_efi_mouse_state cur; + grub_efi_mouse_prot_t *mouse = term->data; + //int x; + int y; + grub_efi_uintn_t i; + if (!mouse) + return GRUB_TERM_NO_KEY; + for (i = 0; i < mouse->count; i++) + { + efi_call_2 (mouse->mouse[i]->get_state, mouse->mouse[i], &cur); + if (grub_memcmp (&cur, &no_move, sizeof (grub_efi_mouse_state)) != 0) + { + y = mouse_div (cur.y, mouse->mouse[i]->mode->y); + if (cur.left) + return 0x0d; + if (cur.right) + return GRUB_TERM_ESC; + if (y > 0) + return GRUB_TERM_KEY_DOWN; + if (y < 0) + return GRUB_TERM_KEY_UP; + } + } + return GRUB_TERM_NO_KEY; +} + +#ifdef MOUSE_DEBUG +static grub_err_t +grub_cmd_mouse_test (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) + +{ + grub_efi_mouse_state cur; + int x = 0, y = 0, z = 0; + grub_efi_uintn_t i; + grub_efi_mouse_prot_t *mouse = NULL; + + mouse = grub_efi_mouse_prot_init (); + if (!mouse) + return grub_error (GRUB_ERR_BAD_OS, "mouse not found.\n"); + grub_printf ("Press [1] to exit.\n"); + while (1) + { + if (grub_getkey_noblock () == '1') + break; + for (i = 0; i < mouse->count; i++) + { + efi_call_2 (mouse->mouse[i]->get_state, mouse->mouse[i], &cur); + if (grub_memcmp (&cur, &no_move, sizeof (grub_efi_mouse_state)) != 0) + { + x = mouse_div (cur.x, mouse->mouse[i]->mode->x); + y = mouse_div (cur.y, mouse->mouse[i]->mode->y); + z = mouse_div (cur.z, mouse->mouse[i]->mode->z); + grub_printf ("[ID=%d] X=%d Y=%d Z=%d L=%d R=%d\n", + (int)i, x, y, z, cur.left, cur.right); + } + } + grub_refresh (); + } + grub_free (mouse->mouse); + grub_free (mouse); + return GRUB_ERR_NONE; +} +static grub_command_t cmd; +#endif + +static struct grub_term_input grub_mouse_term_input = +{ + .name = "mouse", + .getkey = grub_mouse_getkey, + .init = grub_efi_mouse_input_init, +}; + +GRUB_MOD_INIT(mouse) +{ + grub_term_register_input ("mouse", &grub_mouse_term_input); +#ifdef MOUSE_DEBUG + cmd = grub_register_command ("mouse_test", grub_cmd_mouse_test, 0, + N_("UEFI mouse test.")); +#endif +} + +GRUB_MOD_FINI(mouse) +{ + grub_term_unregister_input (&grub_mouse_term_input); +#ifdef MOUSE_DEBUG + grub_unregister_command (cmd); +#endif +} diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c index c5897d9e..61703ef4 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c @@ -3152,7 +3152,7 @@ int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, gr } else { - file->read_hook = (grub_disk_read_hook_t)grub_disk_blocklist_read; + file->read_hook = (void *)grub_disk_blocklist_read; file->read_hook_data = chunklist; for (size = file->size; size > 0; size -= read) diff --git a/GRUB2/MOD_SRC/grub-2.04/install.sh b/GRUB2/MOD_SRC/grub-2.04/install.sh index 5b7175b4..c6b0d0f2 100644 --- a/GRUB2/MOD_SRC/grub-2.04/install.sh +++ b/GRUB2/MOD_SRC/grub-2.04/install.sh @@ -15,7 +15,7 @@ net_modules_legacy="net tftp http" all_modules_legacy="file setkey date drivemap blocklist regexp newc vga_text ntldr search at_keyboard usb_keyboard gcry_md5 hashsum gzio xzio lzopio lspci pci ext2 xfs ventoy chain read halt iso9660 linux16 test true sleep reboot echo videotest videoinfo videotest_checksum video_colors video_cirrus video_bochs vga vbe video_fb font video gettext extcmd terminal linux minicmd help configfile tr trig boot biosdisk disk ls tar squash4 password_pbkdf2 all_video png jpeg part_gpt part_msdos fat exfat ntfs loopback gzio normal udf gfxmenu gfxterm gfxterm_background gfxterm_menu" net_modules_uefi="efinet net tftp http" -all_modules_uefi="file setkey blocklist ventoy test true regexp newc search at_keyboard usb_keyboard gcry_md5 hashsum gzio xzio lzopio ext2 xfs read halt sleep serial terminfo png password_pbkdf2 gcry_sha512 pbkdf2 part_gpt part_msdos ls tar squash4 loopback part_apple minicmd diskfilter linux relocator jpeg iso9660 udf hfsplus halt acpi mmap gfxmenu video_colors trig bitmap_scale gfxterm bitmap font fat exfat ntfs fshelp efifwsetup reboot echo configfile normal terminal gettext chain priority_queue bufio datetime cat extcmd crypto gzio boot all_video efi_gop efi_uga video_bochs video_cirrus video video_fb gfxterm_background gfxterm_menu" +all_modules_uefi="file setkey blocklist ventoy test true regexp newc search at_keyboard usb_keyboard gcry_md5 hashsum gzio xzio lzopio ext2 xfs read halt sleep serial terminfo png password_pbkdf2 gcry_sha512 pbkdf2 part_gpt part_msdos ls tar squash4 loopback part_apple minicmd diskfilter linux relocator jpeg iso9660 udf hfsplus halt acpi mmap gfxmenu video_colors trig bitmap_scale gfxterm bitmap font fat exfat ntfs fshelp efifwsetup reboot echo configfile normal terminal gettext chain priority_queue bufio datetime cat extcmd crypto gzio boot all_video efi_gop efi_uga video_bochs video_cirrus video video_fb gfxterm_background gfxterm_menu mouse" all_modules_arm64_uefi="file setkey blocklist ventoy test true regexp newc search gcry_md5 hashsum gzio xzio lzopio ext2 xfs read halt sleep serial terminfo png password_pbkdf2 gcry_sha512 pbkdf2 part_gpt part_msdos ls tar squash4 loopback part_apple minicmd diskfilter linux jpeg iso9660 udf hfsplus halt acpi mmap gfxmenu video_colors trig bitmap_scale gfxterm bitmap font fat exfat ntfs fshelp efifwsetup reboot echo configfile normal terminal gettext chain priority_queue bufio datetime cat extcmd crypto gzio boot all_video efi_gop video video_fb gfxterm_background gfxterm_menu" diff --git a/GRUB2/MOD_SRC/grub-2.04/util/grub-install.c b/GRUB2/MOD_SRC/grub-2.04/util/grub-install.c index fc4a9dc6..76c7bbe1 100644 --- a/GRUB2/MOD_SRC/grub-2.04/util/grub-install.c +++ b/GRUB2/MOD_SRC/grub-2.04/util/grub-install.c @@ -1165,6 +1165,7 @@ main (int argc, char *argv[]) break; case GRUB_INSTALL_PLATFORM_MIPS64EL_EFI: efi_file = "grubmips64el.efi"; + break; case GRUB_INSTALL_PLATFORM_RISCV32_EFI: efi_file = "grubriscv32.efi"; break;