代码拉取完成,页面将自动刷新
同步操作将从 src-anolis-os/grub2 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Renaud=20M=C3=A9trich?= <[email protected]>
Date: Fri, 18 Dec 2020 15:39:26 +0100
Subject: [PATCH] Add 'at_keyboard_fallback_set' var to force the set manually
This seems required with HP DL380p Gen 8 systems.
Indeed, with this system, we can see the following sequence:
1. controller is queried to get current configuration (returns 0x30 which is quite standard)
2. controller is queried to get the current keyboard set in used, using code 0xf0 (first part)
3. controller answers with 0xfa which means "ACK" (== ok)
4. then we send "0" to tell "we want to know which set your are supporting"
5. controller answers with 0xfa ("ACK")
6. controller should then give us 1, 2, 3 or 0x43, 0x41, 0x3f, but here it gives us 0xfe which means "NACK"
Since there seems no way to determine the current set, and in fact the
controller expects set2 to be used, we need to rely on an environment
variable.
Everything has been tested on this system: using 0xFE (resend command),
making sure we wait for ACK in the 2 steps "write_mode", etc.
Below is litterature I used to come up with "there is no other
solution":
- https://wiki.osdev.org/%228042%22_PS/2_Controller
- http://www-ug.eecg.toronto.edu/msl/nios_devices/datasheets/PS2%20Keyboard%20Protocol.htm
- http://www.s100computers.com/My%20System%20Pages/MSDOS%20Board/PC%20Keyboard.pdf
---
grub-core/term/at_keyboard.c | 121 ++++++++++++++++++++++++++++++++++---------
1 file changed, 96 insertions(+), 25 deletions(-)
diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c
index 69d99b61d..c805cccbd 100644
--- a/grub-core/term/at_keyboard.c
+++ b/grub-core/term/at_keyboard.c
@@ -31,6 +31,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
static grub_uint8_t grub_keyboard_controller_orig;
static grub_uint8_t grub_keyboard_orig_set;
struct grub_ps2_state ps2_state;
+static int fallback_set;
static int ping_sent;
@@ -76,6 +77,8 @@ at_command (grub_uint8_t data)
break;
return 0;
}
+ if (i == GRUB_AT_TRIES)
+ grub_dprintf ("atkeyb", "at_command() timed out! (stopped after %d tries)\n", i);
return (i != GRUB_AT_TRIES);
}
@@ -105,6 +108,21 @@ grub_keyboard_controller_read (void)
#endif
+static int
+resend_last_result (void)
+{
+ grub_uint8_t ret;
+ keyboard_controller_wait_until_ready ();
+ grub_dprintf ("atkeyb", "resend_last_result: sending 0xfe\n");
+ grub_outb (0xfe, KEYBOARD_REG_DATA);
+ ret = wait_ack ();
+ grub_dprintf ("atkeyb", "resend_last_result: wait_ack() returned 0x%x\n", ret);
+ keyboard_controller_wait_until_ready ();
+ ret = grub_inb (KEYBOARD_REG_DATA);
+ grub_dprintf ("atkeyb", "resend_last_result: read 0x%x from controller\n", ret);
+ return ret;
+}
+
static int
write_mode (int mode)
{
@@ -113,11 +131,14 @@ write_mode (int mode)
{
grub_uint8_t ack;
keyboard_controller_wait_until_ready ();
+ grub_dprintf ("atkeyb", "write_mode: sending 0xf0\n");
grub_outb (0xf0, KEYBOARD_REG_DATA);
keyboard_controller_wait_until_ready ();
+ grub_dprintf ("atkeyb", "write_mode: sending mode %d\n", mode);
grub_outb (mode, KEYBOARD_REG_DATA);
keyboard_controller_wait_until_ready ();
ack = wait_ack ();
+ grub_dprintf ("atkeyb", "write_mode: wait_ack() returned 0x%x\n", ack);
if (ack == GRUB_AT_NACK)
continue;
if (ack == GRUB_AT_ACK)
@@ -125,6 +146,9 @@ write_mode (int mode)
return 0;
}
+ if (i == GRUB_AT_TRIES)
+ grub_dprintf ("atkeyb", "write_mode() timed out! (stopped after %d tries)\n", i);
+
return (i != GRUB_AT_TRIES);
}
@@ -132,31 +156,66 @@ static int
query_mode (void)
{
grub_uint8_t ret;
+ grub_uint64_t endtime;
+ unsigned i;
int e;
+ char *envvar;
- e = write_mode (0);
- if (!e) {
- grub_dprintf("atkeyb", "query_mode: write_mode(0) failed\n");
- return 0;
- }
+ for (i = 0; i < GRUB_AT_TRIES; i++) {
+ grub_dprintf ("atkeyb", "query_mode: sending command to controller\n");
+ e = write_mode (0);
+ if (!e) {
+ grub_dprintf ("atkeyb", "query_mode: write_mode(0) failed\n");
+ return 0;
+ }
- do {
- keyboard_controller_wait_until_ready ();
- ret = grub_inb (KEYBOARD_REG_DATA);
- } while (ret == GRUB_AT_ACK);
- /* QEMU translates the set even in no-translate mode. */
- if (ret == 0x43 || ret == 1) {
- grub_dprintf("atkeyb", "query_mode: returning 1 (ret=0x%x)\n", ret);
- return 1;
- }
- if (ret == 0x41 || ret == 2) {
- grub_dprintf("atkeyb", "query_mode: returning 2 (ret=0x%x)\n", ret);
- return 2;
+ endtime = grub_get_time_ms () + 20;
+ do {
+ keyboard_controller_wait_until_ready ();
+ ret = grub_inb (KEYBOARD_REG_DATA);
+ grub_dprintf ("atkeyb", "query_mode/loop: read 0x%x from controller\n", ret);
+ } while ((ret == GRUB_AT_ACK || ret == GRUB_AT_NACK) && grub_get_time_ms () < endtime);
+ if (ret == 0xfe) {
+ grub_dprintf ("atkeyb", "query_mode: asking controller to resend last result\n");
+ ret = resend_last_result();
+ grub_dprintf ("atkeyb", "query_mode: read 0x%x from controller\n", ret);
+ }
+ /* QEMU translates the set even in no-translate mode. */
+ if (ret == 0x43 || ret == 1) {
+ grub_dprintf ("atkeyb", "query_mode: controller returned 0x%x, returning 1\n", ret);
+ return 1;
+ }
+ if (ret == 0x41 || ret == 2) {
+ grub_dprintf ("atkeyb", "query_mode: controller returned 0x%x, returning 2\n", ret);
+ return 2;
+ }
+ if (ret == 0x3f || ret == 3) {
+ grub_dprintf ("atkeyb", "query_mode: controller returned 0x%x, returning 3\n", ret);
+ return 3;
+ }
+ grub_dprintf ("atkeyb", "query_mode: controller returned unexpected value 0x%x, retrying\n", ret);
}
- if (ret == 0x3f || ret == 3) {
- grub_dprintf("atkeyb", "query_mode: returning 3 (ret=0x%x)\n", ret);
- return 3;
+
+ /*
+ * Falling here means we tried querying and the controller returned something
+ * we don't understand, try to use 'at_keyboard_fallback_set' if it exists,
+ * otherwise return 0.
+ */
+ envvar = grub_env_get ("at_keyboard_fallback_set");
+ if (envvar) {
+ fallback_set = grub_strtoul (envvar, 0, 10);
+ if ((grub_errno) || (fallback_set < 1) || (fallback_set > 3)) {
+ grub_dprintf ("atkeyb", "WARNING: ignoring unexpected value '%s' for '%s' variable\n",
+ envvar, "at_keyboard_fallback_set");
+ fallback_set = 0;
+ } else {
+ grub_dprintf ("atkeyb", "query_mode: '%s' specified in environment, returning %d\n",
+ "at_keyboard_fallback_set", fallback_set);
+ }
+ return fallback_set;
}
+ grub_dprintf ("atkeyb", "WARNING: no '%s' specified in environment, returning 0\n",
+ "at_keyboard_fallback_set");
return 0;
}
@@ -165,14 +224,25 @@ set_scancodes (void)
{
/* You must have visited computer museum. Keyboard without scancode set
knowledge. Assume XT. */
- if (!grub_keyboard_orig_set)
- {
- grub_dprintf ("atkeyb", "No sets support assumed\n");
- ps2_state.current_set = 1;
+ if (!grub_keyboard_orig_set) {
+ if (fallback_set) {
+ grub_dprintf ("atkeyb", "No sets support assumed but set forced to %d\n", fallback_set);
+ ps2_state.current_set = fallback_set;
return;
}
+ grub_dprintf ("atkeyb", "No sets support assumed, forcing to set 1\n");
+ ps2_state.current_set = 1;
+ return;
+ }
#if !USE_SCANCODE_SET
+ if (fallback_set) {
+ grub_dprintf ("atkeyb", "queried set is %d but set forced to %d\n",
+ grub_keyboard_orig_set, fallback_set);
+ ps2_state.current_set = fallback_set;
+ return;
+ }
+
if ((grub_keyboard_controller_orig & KEYBOARD_AT_TRANSLATE) == KEYBOARD_AT_TRANSLATE) {
grub_dprintf ("atkeyb", "queried set is %d but keyboard in Translate mode, so actually in set 1\n", grub_keyboard_orig_set);
ps2_state.current_set = 1;
@@ -261,6 +331,7 @@ grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
static void
grub_keyboard_controller_init (void)
{
+ grub_dprintf ("atkeyb", "initializing the controller\n");
ps2_state.at_keyboard_status = 0;
/* Drain input buffer. */
while (1)
@@ -282,6 +353,7 @@ grub_keyboard_controller_init (void)
grub_keyboard_controller_orig = grub_keyboard_controller_read ();
grub_dprintf ("atkeyb", "grub_keyboard_controller_orig = 0x%x\n", grub_keyboard_controller_orig);
grub_keyboard_orig_set = query_mode ();
+ grub_dprintf ("atkeyb", "grub_keyboard_orig_set = %d\n", grub_keyboard_orig_set);
#endif
set_scancodes ();
keyboard_controller_led (ps2_state.led_status);
@@ -329,7 +401,6 @@ grub_at_restore_hw (void)
return GRUB_ERR_NONE;
}
-
static struct grub_term_input grub_at_keyboard_term =
{
.name = "at_keyboard",
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。