diff options
author | Michael Brown <mcb30@ipxe.org> | 2022-02-09 16:06:11 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2022-02-10 13:11:27 +0000 |
commit | fa708015e545a5877b1c07e2acf40f25b333c2cd (patch) | |
tree | 86e889d7624d9b88a338fca41c04eb00b8695a14 | |
parent | f51a62bc3f7abb40e331c16df1f4d9314aefaf23 (diff) | |
download | ipxe-fa708015e545a5877b1c07e2acf40f25b333c2cd.zip ipxe-fa708015e545a5877b1c07e2acf40f25b333c2cd.tar.gz ipxe-fa708015e545a5877b1c07e2acf40f25b333c2cd.tar.bz2 |
[console] Avoid attempting to remap numeric keypad on BIOS console
To minimise code size, our keyboard mapping works on the basis of
allowing the BIOS to convert the keyboard scancode into an ASCII
character and then remapping the ASCII character.
This causes problems with keyboard layouts such as "fr" that swap the
shifted and unshifted digit keys, since the ASCII-based remapping will
spuriously remap the numeric keypad (which produces the same ASCII
values as the digit keys).
Fix by checking that the keyboard scancode is within the range of keys
that vary between keyboard mappings before attempting to remap the
ASCII character.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/arch/x86/interface/pcbios/bios_console.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/src/arch/x86/interface/pcbios/bios_console.c b/src/arch/x86/interface/pcbios/bios_console.c index 0692e7a..443513e 100644 --- a/src/arch/x86/interface/pcbios/bios_console.c +++ b/src/arch/x86/interface/pcbios/bios_console.c @@ -60,6 +60,14 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define ATTR_DEFAULT ATTR_FCOL_WHITE +/** Maximum keycode subject to remapping + * + * This allows us to avoid remapping the numeric keypad, which is + * necessary for keyboard layouts such as "fr" that swap the shifted + * and unshifted digit keys. + */ +#define SCANCODE_RSHIFT 0x36 + /* Set default console usage if applicable */ #if ! ( defined ( CONSOLE_PCBIOS ) && CONSOLE_EXPLICIT ( CONSOLE_PCBIOS ) ) #undef CONSOLE_PCBIOS @@ -346,6 +354,7 @@ static const char * bios_ansi_seq ( unsigned int scancode ) { */ static int bios_getchar ( void ) { uint16_t keypress; + unsigned int scancode; unsigned int character; const char *ansi_seq; @@ -367,11 +376,17 @@ static int bios_getchar ( void ) { : "=a" ( keypress ) : "a" ( 0x1000 ), "m" ( bios_inject_lock ) ); bios_inject_lock--; + scancode = ( keypress >> 8 ); character = ( keypress & 0xff ); - /* If it's a normal character, just map and return it */ - if ( character && ( character < 0x80 ) ) - return key_remap ( character ); + /* If it's a normal character, map (if applicable) and return it */ + if ( character && ( character < 0x80 ) ) { + if ( scancode < SCANCODE_RSHIFT ) { + return key_remap ( character ); + } else { + return character; + } + } /* Otherwise, check for a special key that we know about */ if ( ( ansi_seq = bios_ansi_seq ( keypress >> 8 ) ) ) { |