]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/term/setkey.c
Merge branch 'master' of https://github.com/ventoy/Ventoy
[Ventoy.git] / GRUB2 / MOD_SRC / grub-2.04 / grub-core / term / setkey.c
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2020 Free Software Foundation, Inc.
4 *
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <grub/types.h>
20 #include <grub/misc.h>
21 #include <grub/mm.h>
22 #include <grub/env.h>
23 #include <grub/err.h>
24 #include <grub/dl.h>
25 #include <grub/extcmd.h>
26 #include <grub/i18n.h>
27 #include <grub/term.h>
28
29 GRUB_MOD_LICENSE ("GPLv3+");
30
31 #define MAX_KEYMAP 255
32
33 struct keymap
34 {
35 int cnt;
36 int in[MAX_KEYMAP];
37 int out[MAX_KEYMAP];
38 };
39
40 static struct keymap setkey_keymap;
41
42 struct keysym
43 {
44 const char *name; /* the name in unshifted state */
45 int code; /* scan code */
46 };
47
48 /* The table for key symbols. (from GRUB4DOS) */
49 static struct keysym keysym_table[] =
50 {
51 {"escape", GRUB_TERM_ESC}, // ESC
52 {"exclam", 0x21}, // '!'
53 {"at", 0x40}, // '@'
54 {"numbersign", 0x23}, // '#'
55 {"dollar", 0x24}, // '$'
56 {"percent", 0x25}, // '%'
57 {"caret", 0x5E}, // '^'
58 {"ampersand", 0x26}, // '&'
59 {"asterisk", 0x2A}, // '*'
60 {"parenleft", 0x28}, // '('
61 {"parenright", 0x29}, // ')'
62 {"minus", 0x2D}, // '-'
63 {"underscore", 0x5F}, // '_'
64 {"equal", 0x3D}, // '='
65 {"plus", 0x2B}, // '+'
66 {"backspace", GRUB_TERM_BACKSPACE}, // BS
67 {"ctrlbackspace", GRUB_TERM_CTRL | GRUB_TERM_BACKSPACE}, // (DEL)
68 {"tab", GRUB_TERM_TAB}, // Tab
69 {"bracketleft", 0x5B}, // '['
70 {"braceleft", 0x7B}, // '{'
71 {"bracketright", 0x5D}, // ']'
72 {"braceright", 0x7D}, // '}'
73 {"enter", 0x0D}, // Enter
74 {"semicolon", 0x3B}, // ';'
75 {"colon", 0x3A}, // ':'
76 {"quote", 0x27}, // '\''
77 {"doublequote", 0x22}, // '"'
78 {"backquote", 0x60}, // '`'
79 {"tilde", 0x7E}, // '~'
80 {"backslash", 0x5C}, // '\\'
81 {"bar", 0x7C}, // '|'
82 {"comma", 0x2C}, // ','
83 {"less", 0x3C}, // '<'
84 {"period", 0x2E}, // '.'
85 {"greater", 0x3E}, // '>'
86 {"slash", 0x2F}, // '/'
87 {"question", 0x3F}, // '?'
88 {"space", 0x20}, // Space
89 {"F1", GRUB_TERM_KEY_F1},
90 {"F2", GRUB_TERM_KEY_F2},
91 {"F3", GRUB_TERM_KEY_F3},
92 {"F4", GRUB_TERM_KEY_F4},
93 {"F5", GRUB_TERM_KEY_F5},
94 {"F6", GRUB_TERM_KEY_F6},
95 {"F7", GRUB_TERM_KEY_F7},
96 {"F8", GRUB_TERM_KEY_F8},
97 {"F9", GRUB_TERM_KEY_F9},
98 {"F10", GRUB_TERM_KEY_F10},
99 {"F11", GRUB_TERM_KEY_F11},
100 {"F12", GRUB_TERM_KEY_F12},
101 {"home", GRUB_TERM_KEY_HOME},
102 {"uparrow", GRUB_TERM_KEY_UP},
103 {"pageup", GRUB_TERM_KEY_NPAGE}, // PgUp
104 {"leftarrow", GRUB_TERM_KEY_LEFT},
105 {"center", GRUB_TERM_KEY_CENTER}, // keypad center key
106 {"rightarrow", GRUB_TERM_KEY_RIGHT},
107 {"end", GRUB_TERM_KEY_END},
108 {"downarrow", GRUB_TERM_KEY_DOWN},
109 {"pagedown", GRUB_TERM_KEY_PPAGE}, // PgDn
110 {"insert", GRUB_TERM_KEY_INSERT}, // Insert
111 {"delete", GRUB_TERM_KEY_DC}, // Delete
112 {"shiftF1", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F1},
113 {"shiftF2", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F2},
114 {"shiftF3", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F3},
115 {"shiftF4", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F4},
116 {"shiftF5", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F5},
117 {"shiftF6", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F6},
118 {"shiftF7", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F7},
119 {"shiftF8", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F8},
120 {"shiftF9", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F9},
121 {"shiftF10", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F10},
122 {"shiftF11", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F11},
123 {"shiftF12", GRUB_TERM_SHIFT | GRUB_TERM_KEY_F12},
124 {"ctrlF1", GRUB_TERM_CTRL | GRUB_TERM_KEY_F1},
125 {"ctrlF2", GRUB_TERM_CTRL | GRUB_TERM_KEY_F2},
126 {"ctrlF3", GRUB_TERM_CTRL | GRUB_TERM_KEY_F3},
127 {"ctrlF4", GRUB_TERM_CTRL | GRUB_TERM_KEY_F4},
128 {"ctrlF5", GRUB_TERM_CTRL | GRUB_TERM_KEY_F5},
129 {"ctrlF6", GRUB_TERM_CTRL | GRUB_TERM_KEY_F6},
130 {"ctrlF7", GRUB_TERM_CTRL | GRUB_TERM_KEY_F7},
131 {"ctrlF8", GRUB_TERM_CTRL | GRUB_TERM_KEY_F8},
132 {"ctrlF9", GRUB_TERM_CTRL | GRUB_TERM_KEY_F9},
133 {"ctrlF10", GRUB_TERM_CTRL | GRUB_TERM_KEY_F10},
134 {"ctrlF11", GRUB_TERM_CTRL | GRUB_TERM_KEY_F11},
135 {"ctrlF12", GRUB_TERM_CTRL | GRUB_TERM_KEY_F12},
136 // A=Alt or AltGr. Provided by steve.
137 {"Aq", GRUB_TERM_ALT | 0x71},
138 {"Aw", GRUB_TERM_ALT | 0x77},
139 {"Ae", GRUB_TERM_ALT | 0x65},
140 {"Ar", GRUB_TERM_ALT | 0x72},
141 {"At", GRUB_TERM_ALT | 0x74},
142 {"Ay", GRUB_TERM_ALT | 0x79},
143 {"Au", GRUB_TERM_ALT | 0x75},
144 {"Ai", GRUB_TERM_ALT | 0x69},
145 {"Ao", GRUB_TERM_ALT | 0x6F},
146 {"Ap", GRUB_TERM_ALT | 0x70},
147 {"Aa", GRUB_TERM_ALT | 0x61},
148 {"As", GRUB_TERM_ALT | 0x73},
149 {"Ad", GRUB_TERM_ALT | 0x64},
150 {"Af", GRUB_TERM_ALT | 0x66},
151 {"Ag", GRUB_TERM_ALT | 0x67},
152 {"Ah", GRUB_TERM_ALT | 0x68},
153 {"Aj", GRUB_TERM_ALT | 0x6A},
154 {"Ak", GRUB_TERM_ALT | 0x6B},
155 {"Al", GRUB_TERM_ALT | 0x6C},
156 {"Az", GRUB_TERM_ALT | 0x7A},
157 {"Ax", GRUB_TERM_ALT | 0x78},
158 {"Ac", GRUB_TERM_ALT | 0x63},
159 {"Av", GRUB_TERM_ALT | 0x76},
160 {"Ab", GRUB_TERM_ALT | 0x62},
161 {"An", GRUB_TERM_ALT | 0x6E},
162 {"Am", GRUB_TERM_ALT | 0x6D},
163 {"A1", GRUB_TERM_ALT | 0x31},
164 {"A2", GRUB_TERM_ALT | 0x32},
165 {"A3", GRUB_TERM_ALT | 0x33},
166 {"A4", GRUB_TERM_ALT | 0x34},
167 {"A5", GRUB_TERM_ALT | 0x35},
168 {"A6", GRUB_TERM_ALT | 0x36},
169 {"A7", GRUB_TERM_ALT | 0x37},
170 {"A8", GRUB_TERM_ALT | 0x38},
171 {"A9", GRUB_TERM_ALT | 0x39},
172 {"A0", GRUB_TERM_ALT | 0x30},
173 //{"oem102", 0x5c},
174 //{"shiftoem102", 0x7c},
175 {"Aminus", GRUB_TERM_ALT | 0x2D},
176 {"Aequal", GRUB_TERM_ALT | 0x3D},
177 {"Abracketleft", GRUB_TERM_ALT | 0x5B},
178 {"Abracketright", GRUB_TERM_ALT | 0x5D},
179 {"Asemicolon", GRUB_TERM_ALT | 0x3B},
180 {"Aquote", GRUB_TERM_ALT | 0x27},
181 {"Abackquote", GRUB_TERM_ALT | 0x60},
182 {"Abackslash", GRUB_TERM_ALT | 0x5C},
183 {"Acomma", GRUB_TERM_ALT | 0x2C},
184 {"Aperiod", GRUB_TERM_ALT | 0x2E},
185 {"Aslash", GRUB_TERM_ALT | 0x2F},
186 {"Acolon", GRUB_TERM_ALT | 0x3A},
187 {"Aplus", GRUB_TERM_ALT | 0x2B},
188 {"Aless", GRUB_TERM_ALT | 0x3C},
189 {"Aunderscore", GRUB_TERM_ALT | 0x5F},
190 {"Agreater", GRUB_TERM_ALT | 0x3E},
191 {"Aquestion", GRUB_TERM_ALT | 0x3F},
192 {"Atilde", GRUB_TERM_ALT | 0x7E},
193 {"Abraceleft", GRUB_TERM_ALT | 0x7B},
194 {"Abar", GRUB_TERM_ALT | 0x7C},
195 {"Abraceright", GRUB_TERM_ALT | 0x7D},
196 {"Adoublequote", GRUB_TERM_ALT | 0x22},
197 };
198
199 static int grub_keymap_getkey (int key)
200 {
201 int i;
202 if (key == GRUB_TERM_NO_KEY)
203 return key;
204 if (setkey_keymap.cnt > MAX_KEYMAP)
205 setkey_keymap.cnt = MAX_KEYMAP;
206 for (i = 0; i < setkey_keymap.cnt; i++)
207 {
208 if (key == setkey_keymap.in[i])
209 {
210 key = setkey_keymap.out[i];
211 break;
212 }
213 }
214 return key;
215 }
216
217 static void
218 grub_keymap_reset (void)
219 {
220 grub_memset (&setkey_keymap, 0, sizeof (struct keymap));
221 }
222
223 static grub_err_t
224 grub_keymap_add (int in, int out)
225 {
226 if (in == GRUB_TERM_NO_KEY || out == GRUB_TERM_NO_KEY)
227 return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid key: %d -> %d", in, out);
228 if (setkey_keymap.cnt >= MAX_KEYMAP)
229 return grub_error (GRUB_ERR_OUT_OF_MEMORY,
230 "keymap FULL %d", setkey_keymap.cnt);
231 setkey_keymap.in[setkey_keymap.cnt] = in;
232 setkey_keymap.out[setkey_keymap.cnt] = out;
233 setkey_keymap.cnt++;
234 return GRUB_ERR_NONE;
235 }
236
237 static void
238 grub_keymap_enable (void)
239 {
240 grub_key_remap = grub_keymap_getkey;
241 }
242
243 static void
244 grub_keymap_disable (void)
245 {
246 grub_key_remap = NULL;
247 }
248
249 static void
250 grub_keymap_status (void)
251 {
252 int i;
253 if (setkey_keymap.cnt > MAX_KEYMAP)
254 setkey_keymap.cnt = MAX_KEYMAP;
255 for (i = 0; i < setkey_keymap.cnt; i++)
256 {
257 grub_printf ("0x%x -> 0x%x\n", setkey_keymap.in[i], setkey_keymap.out[i]);
258 }
259 }
260
261 static const struct grub_arg_option options[] =
262 {
263 {"reset", 'r', 0, N_("Reset keymap."), 0, 0},
264 {"enable", 'e', 0, N_("Enable keymap."), 0, 0},
265 {"disable", 'd', 0, N_("Disable keymap."), 0, 0},
266 {"status", 's', 0, N_("Display keymap."), 0, 0},
267 {0, 0, 0, 0, 0, 0}
268 };
269
270 enum options
271 {
272 SETKEY_RESET,
273 SETKEY_ENABLE,
274 SETKEY_DISABLE,
275 SETKEY_STATUS,
276 };
277
278 static int
279 ishex (const char *str)
280 {
281 if (grub_strlen (str) < 3 || str[0] != '0')
282 return 0;
283 if (str[1] != 'x' && str[1] != 'X')
284 return 0;
285 return 1;
286 }
287
288 static int
289 parse_key (const char *str)
290 {
291 int i;
292 if (ishex (str))
293 return grub_strtol (str, NULL, 16);
294 if (grub_strlen (str) == 1)
295 return (int) str[0];
296 for (i = 0; i < (int) (sizeof (keysym_table) / sizeof (keysym_table[0])); i++)
297 {
298 if (grub_strcmp (str, keysym_table[i].name) == 0)
299 return keysym_table[i].code;
300 }
301 grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid key %s", str);
302 return 0;
303 }
304
305 static grub_err_t
306 grub_cmd_setkey (grub_extcmd_context_t ctxt, int argc, char **args)
307 {
308 struct grub_arg_list *state = ctxt->state;
309 int in, out;
310 if (state[SETKEY_ENABLE].set)
311 {
312 grub_keymap_enable ();
313 goto out;
314 }
315 if (state[SETKEY_DISABLE].set)
316 {
317 grub_keymap_disable ();
318 goto out;
319 }
320 if (state[SETKEY_RESET].set)
321 {
322 grub_keymap_reset ();
323 goto out;
324 }
325 if (state[SETKEY_STATUS].set)
326 {
327 grub_keymap_status ();
328 goto out;
329 }
330 if (argc != 2)
331 {
332 grub_printf
333 ("Key names: 0-9, A-Z, a-z or escape, exclam, at, numbersign, dollar,"
334 "percent, caret, ampersand, asterisk, parenleft, parenright, minus,"
335 "underscore, equal, plus, backspace, tab, bracketleft, braceleft,"
336 "bracketright, braceright, enter, semicolon, colon, quote, doublequote,"
337 "backquote, tilde, backslash, bar, comma, less, period, greater,"
338 "slash, question, alt, space, delete, [ctrl|shift]F1-12."
339 "For Alt+ prefix with A, e.g. \'setkey at Aequal\'.");
340 goto out;
341 }
342 in = parse_key (args[1]);
343 out = parse_key (args[0]);
344 if (!in || !out)
345 goto out;
346 grub_keymap_add (in, out);
347 out:
348 return grub_errno;
349 }
350
351 static void grub_keymap_add_by_string(const char *src, const char *dst)
352 {
353 int in = 0;
354 int out = 0;
355
356 in = parse_key(dst);
357 out = parse_key(src);
358
359 if (in && out)
360 {
361 grub_keymap_add (in, out);
362 }
363 }
364
365 #include "keyboard_layout.c"
366
367 static grub_err_t grub_cmd_set_keylayout (grub_extcmd_context_t ctxt, int argc, char **args)
368 {
369 (void)ctxt;
370 (void)argc;
371 ventoy_set_keyboard_layout(args[0]);
372 return 0;
373 }
374
375 static grub_extcmd_t cmd, setcmd;
376
377 GRUB_MOD_INIT(setkey)
378 {
379 cmd = grub_register_extcmd ("setkey", grub_cmd_setkey, 0, N_("NEW_KEY USA_KEY"),
380 N_("Map default USA_KEY to NEW_KEY."), options);
381 setcmd = grub_register_extcmd ("set_keyboard_layout", grub_cmd_set_keylayout, 0, N_("layout"),
382 N_("Set keyboard layout."), NULL);
383 }
384
385 GRUB_MOD_FINI(setkey)
386 {
387 grub_unregister_extcmd (cmd);
388 }