Bug #141
open
GRUB payload hangs in HP Elitebooks
Added by Iru Cai about 7 years ago.
Updated over 1 year ago.
Description
There may be some problem when initializing the keyboard controller, but SeaBIOS payload works fine. Using GRUB payload directly or chainload GRUB payload with SeaBIOS will both hang the system.
I modified GRUB and find it hangs in set_scancodes(void), when calling the first write_mode. After grub_outb (mode, KEYBOARD_REG_DATA);
, the keyboard_controller_wait_until_ready()
function goes to an infinite loop.
write_mode (int mode)
{
unsigned i;
for (i = 0; i < GRUB_AT_TRIES; i++)
{
grub_uint8_t ack;
keyboard_controller_wait_until_ready ();
grub_outb (0xf0, KEYBOARD_REG_DATA);
keyboard_controller_wait_until_ready ();
grub_outb (mode, KEYBOARD_REG_DATA);
keyboard_controller_wait_until_ready ();
ack = wait_ack ();
if (ack == GRUB_AT_NACK)
continue;
if (ack == GRUB_AT_ACK)
break;
return 0;
}
return (i != GRUB_AT_TRIES);
}
Files
I guess Linux works fine too. What about libpayload based payloads?
Can you please attach the debug logs of SeaBIOS (yes not GRUB) with debug log level.
I've just made a SeaBIOS log (verbosity 7).
Thank you. SeaBIOS does:
$ grep 7fee4000 seabios.log
/7fee4000\ Start thread
|7fee4000| i8042_flush
|7fee4000| i8042_command cmd=ad
|7fee4000| i8042_wait_write
|7fee4000| i8042_command cmd=a7
|7fee4000| i8042_wait_write
|7fee4000| i8042_flush
|7fee4000| i8042_command cmd=1aa
|7fee4000| i8042_wait_write
|7fee4000| i8042_wait_read
|7fee4000| i8042 param=55
|7fee4000| i8042_command cmd=1ab
|7fee4000| i8042_wait_write
|7fee4000| i8042_wait_read
|7fee4000| i8042 param=0
|7fee4000| ps2_command aux=0 cmd=1ff
|7fee4000| i8042 ctr old=30 new=30
|7fee4000| i8042_command cmd=1060
|7fee4000| i8042_wait_write
|7fee4000| i8042_wait_write
|7fee4000| i8042_command cmd=1060
|7fee4000| i8042_wait_write
|7fee4000| i8042_wait_write
|7fee4000| ps2_sendbyte aux=0 cmd=ff
|7fee4000| i8042_kbd_write c=255
|7fee4000| i8042_wait_write
|7fee4000| ps2 read fa
|7fee4000| ps2 read aa
|7fee4000| i8042_command cmd=1060
|7fee4000| i8042_wait_write
|7fee4000| i8042_wait_write
|7fee4000| ps2_command aux=0 cmd=f5
|7fee4000| i8042 ctr old=30 new=30
|7fee4000| i8042_command cmd=1060
|7fee4000| i8042_wait_write
|7fee4000| i8042_wait_write
|7fee4000| i8042_command cmd=1060
|7fee4000| i8042_wait_write
|7fee4000| i8042_wait_write
|7fee4000| ps2_sendbyte aux=0 cmd=f5
|7fee4000| i8042_kbd_write c=245
|7fee4000| i8042_wait_write
|7fee4000| ps2 read fa
|7fee4000| i8042_command cmd=1060
|7fee4000| i8042_wait_write
|7fee4000| i8042_wait_write
|7fee4000| ps2_command aux=0 cmd=10f0
|7fee4000| i8042 ctr old=30 new=30
|7fee4000| i8042_command cmd=1060
|7fee4000| i8042_wait_write
|7fee4000| i8042_wait_write
|7fee4000| i8042_command cmd=1060
|7fee4000| i8042_wait_write
|7fee4000| i8042_wait_write
|7fee4000| ps2_sendbyte aux=0 cmd=f0
|7fee4000| i8042_kbd_write c=240
|7fee4000| i8042_wait_write
|7fee4000| ps2 read fa
|7fee4000| ps2_sendbyte aux=0 cmd=2
|7fee4000| i8042_kbd_write c=2
|7fee4000| i8042_wait_write
|7fee4000| ps2 read fa
|7fee4000| i8042_command cmd=1060
|7fee4000| i8042_wait_write
|7fee4000| i8042_wait_write
|7fee4000| ps2_command aux=0 cmd=f4
|7fee4000| i8042 ctr old=61 new=70
|7fee4000| i8042_command cmd=1060
|7fee4000| i8042_wait_write
|7fee4000| i8042_wait_write
|7fee4000| i8042_command cmd=1060
|7fee4000| i8042_wait_write
|7fee4000| i8042_wait_write
|7fee4000| ps2_sendbyte aux=0 cmd=f4
|7fee4000| i8042_kbd_write c=244
|7fee4000| i8042_wait_write
|7fee4000| ps2 read fa
|7fee4000| i8042_command cmd=1060
|7fee4000| i8042_wait_write
|7fee4000| i8042_wait_write
|7fee4000| PS2 keyboard initialized
\7fee4000/ End thread
Now, one has to find out, what GRUB is doing.
As you found out, that it’s hanging below
static void
keyboard_controller_wait_until_ready (void)
{
/* 50 us would be enough but our current time resolution is 1ms. */
grub_millisleep (1);
while (! KEYBOARD_COMMAND_ISREADY (grub_inb (KEYBOARD_REG_STATUS)));
}
What about adding a timeout there too?
#define KEYBOARD_COMMAND_ISREADY(x) !((x) & 0x02)
Encountered this while porting Libreboot to 2560p and 9470m. Added a 200 ms timeout in keyboard_controller_wait_until_ready, and everything works fine on both machines now. I'll be contacting upstream. Patch attached for anyone curious.
Edit: Opened a ticket at GRUB: https://savannah.gnu.org/bugs/?64090
Also available in: Atom
PDF