aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2023-07-04 14:31:07 +0100
committerMichael Brown <mcb30@ipxe.org>2023-07-04 14:33:43 +0100
commit3ef4f7e2ef4a22ea1e2eccc72957d7bf3fe2f945 (patch)
tree9ae790d320e9410b4dfa58a57cf3b51e418b0de6
parentcc07ed7c7ede8dfc79643ccabb32285c74d6bff5 (diff)
downloadipxe-3ef4f7e2ef4a22ea1e2eccc72957d7bf3fe2f945.zip
ipxe-3ef4f7e2ef4a22ea1e2eccc72957d7bf3fe2f945.tar.gz
ipxe-3ef4f7e2ef4a22ea1e2eccc72957d7bf3fe2f945.tar.bz2
[console] Avoid overlap between special keys and Unicode characters
The special key range (from KEY_MIN upwards) currently overlaps with the valid range for Unicode characters, and therefore prohibits the use of Unicode key values outside the ASCII range. Create space for Unicode key values by moving the special keys to the range immediately above the maximum valid Unicode character. This allows the existing encoding of special keys as an efficiently packed representation of the equivalent ANSI escape sequence to be maintained almost as-is. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/arch/x86/interface/pcbios/bios_console.c59
-rw-r--r--src/drivers/usb/usbkbd.c4
-rw-r--r--src/include/ipxe/keys.h45
3 files changed, 77 insertions, 31 deletions
diff --git a/src/arch/x86/interface/pcbios/bios_console.c b/src/arch/x86/interface/pcbios/bios_console.c
index 0220c85..7263eb7 100644
--- a/src/arch/x86/interface/pcbios/bios_console.c
+++ b/src/arch/x86/interface/pcbios/bios_console.c
@@ -290,29 +290,38 @@ static const char *bios_ansi_input = "";
struct bios_key {
/** Scancode */
uint8_t scancode;
- /** Key code */
- uint16_t key;
+ /** Relative key value */
+ uint16_t rkey;
} __attribute__ (( packed ));
+/**
+ * Define a BIOS key mapping
+ *
+ * @v scancode Scancode
+ * @v key iPXE key code
+ * @v bioskey BIOS key mapping
+ */
+#define BIOS_KEY( scancode, key ) { scancode, KEY_REL ( key ) }
+
/** Mapping from BIOS scan codes to iPXE key codes */
static const struct bios_key bios_keys[] = {
- { 0x53, KEY_DC },
- { 0x48, KEY_UP },
- { 0x50, KEY_DOWN },
- { 0x4b, KEY_LEFT },
- { 0x4d, KEY_RIGHT },
- { 0x47, KEY_HOME },
- { 0x4f, KEY_END },
- { 0x49, KEY_PPAGE },
- { 0x51, KEY_NPAGE },
- { 0x3f, KEY_F5 },
- { 0x40, KEY_F6 },
- { 0x41, KEY_F7 },
- { 0x42, KEY_F8 },
- { 0x43, KEY_F9 },
- { 0x44, KEY_F10 },
- { 0x85, KEY_F11 },
- { 0x86, KEY_F12 },
+ BIOS_KEY ( 0x53, KEY_DC ),
+ BIOS_KEY ( 0x48, KEY_UP ),
+ BIOS_KEY ( 0x50, KEY_DOWN ),
+ BIOS_KEY ( 0x4b, KEY_LEFT ),
+ BIOS_KEY ( 0x4d, KEY_RIGHT ),
+ BIOS_KEY ( 0x47, KEY_HOME ),
+ BIOS_KEY ( 0x4f, KEY_END ),
+ BIOS_KEY ( 0x49, KEY_PPAGE ),
+ BIOS_KEY ( 0x51, KEY_NPAGE ),
+ BIOS_KEY ( 0x3f, KEY_F5 ),
+ BIOS_KEY ( 0x40, KEY_F6 ),
+ BIOS_KEY ( 0x41, KEY_F7 ),
+ BIOS_KEY ( 0x42, KEY_F8 ),
+ BIOS_KEY ( 0x43, KEY_F9 ),
+ BIOS_KEY ( 0x44, KEY_F10 ),
+ BIOS_KEY ( 0x85, KEY_F11 ),
+ BIOS_KEY ( 0x86, KEY_F12 ),
};
/**
@@ -323,7 +332,7 @@ static const struct bios_key bios_keys[] = {
*/
static const char * bios_ansi_seq ( unsigned int scancode ) {
static char buf[ 5 /* "[" + two digits + terminator + NUL */ ];
- unsigned int key;
+ unsigned int rkey;
unsigned int terminator;
unsigned int n;
unsigned int i;
@@ -338,9 +347,9 @@ static const char * bios_ansi_seq ( unsigned int scancode ) {
continue;
/* Construct escape sequence */
- key = bios_keys[i].key;
- n = KEY_ANSI_N ( key );
- terminator = KEY_ANSI_TERMINATOR ( key );
+ rkey = bios_keys[i].rkey;
+ n = KEY_ANSI_N ( rkey );
+ terminator = KEY_ANSI_TERMINATOR ( rkey );
*(tmp++) = '[';
if ( n )
tmp += sprintf ( tmp, "%d", n );
@@ -479,6 +488,7 @@ struct console_driver bios_console __console_driver = {
static __asmcall __used void bios_inject ( struct i386_all_regs *ix86 ) {
unsigned int discard_a;
unsigned int scancode;
+ unsigned int rkey;
unsigned int i;
uint16_t keypress;
int key;
@@ -521,9 +531,10 @@ static __asmcall __used void bios_inject ( struct i386_all_regs *ix86 ) {
/* Handle special keys */
if ( key >= KEY_MIN ) {
+ rkey = KEY_REL ( key );
for ( i = 0 ; i < ( sizeof ( bios_keys ) /
sizeof ( bios_keys[0] ) ) ; i++ ) {
- if ( bios_keys[i].key == key ) {
+ if ( bios_keys[i].rkey == rkey ) {
scancode = bios_keys[i].scancode;
keypress = ( scancode << 8 );
break;
diff --git a/src/drivers/usb/usbkbd.c b/src/drivers/usb/usbkbd.c
index b284e58..cf881ad 100644
--- a/src/drivers/usb/usbkbd.c
+++ b/src/drivers/usb/usbkbd.c
@@ -95,7 +95,7 @@ static unsigned int usbkbd_map ( unsigned int keycode, unsigned int modifiers,
}
} else if ( keycode <= USBKBD_KEY_UP ) {
/* Special keys */
- static const uint16_t special[] = {
+ static const unsigned int special[] = {
0, 0, 0, 0, 0, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9,
KEY_F10, KEY_F11, KEY_F12, 0, 0, 0, KEY_IC, KEY_HOME,
KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT,
@@ -110,7 +110,7 @@ static unsigned int usbkbd_map ( unsigned int keycode, unsigned int modifiers,
if ( leds & USBKBD_LED_NUM_LOCK ) {
key = "1234567890." [ keycode - USBKBD_KEY_PAD_1 ];
} else {
- static const uint16_t keypad[] = {
+ static const unsigned int keypad[] = {
KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, 0,
KEY_RIGHT, KEY_HOME, KEY_UP, KEY_PPAGE,
KEY_IC, KEY_DC
diff --git a/src/include/ipxe/keys.h b/src/include/ipxe/keys.h
index d15267a..2335691 100644
--- a/src/include/ipxe/keys.h
+++ b/src/include/ipxe/keys.h
@@ -49,19 +49,54 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define ESC 0x1b
/*
- * Special keys outside the normal ASCII range
- *
+ * Special keys outside the normal Unicode range
*
* The names are chosen to match those used by curses. The values are
* chosen to facilitate easy conversion from a received ANSI escape
* sequence to a KEY_XXX constant.
*/
-#define KEY_ANSI( n, terminator ) ( 0x100 * ( (n) + 1 ) + (terminator) )
-#define KEY_ANSI_N( key ) ( ( (key) / 0x100 ) - 1 )
+/**
+ * Minimum value for special keypresses
+ *
+ * This value is chosen to lie above the maximum Unicode code point
+ * value 0x10ffff.
+ */
+#define KEY_MIN 0x110000
+
+/**
+ * Construct relative key value for special key
+ *
+ * @v key Key value
+ * @ret rkey Relative key value
+ */
+#define KEY_REL( key ) ( (key) - KEY_MIN )
+
+/**
+ * Construct ANSI escape sequence key value
+ *
+ * @v n ANSI escape sequence numeric portion, or 0 for none
+ * @v terminator ANSI escape sequence terminating character
+ * @ret key Key value
+ */
+#define KEY_ANSI( n, terminator ) ( KEY_MIN + ( (n) << 8 ) + (terminator) )
+
+/**
+ * Extract ANSI escape sequence numeric portion
+ *
+ * @v key Key value (or relative key value)
+ * @ret n ANSI escape sequence numeric portion, or 0 for none
+ */
+#define KEY_ANSI_N( key ) ( ( (key) >> 8 ) & 0xff )
+
+/**
+ * Extract ANSI escape sequence terminating character
+ *
+ * @v key Key value (or relative key value)
+ * @ret terminator ANSI escape sequence terminating character
+ */
#define KEY_ANSI_TERMINATOR( key ) ( (key) & 0xff )
-#define KEY_MIN 0x101
#define KEY_UP KEY_ANSI ( 0, 'A' ) /**< Up arrow */
#define KEY_DOWN KEY_ANSI ( 0, 'B' ) /**< Down arrow */
#define KEY_RIGHT KEY_ANSI ( 0, 'C' ) /**< Right arrow */