Project

General

Profile

Actions

Bug #141

open

GRUB payload hangs in HP Elitebooks

Added by Iru Cai about 6 years ago. Updated 4 months ago.

Status:
New
Priority:
Normal
Assignee:
Category:
-
Target version:
-
Start date:
09/19/2017
Due date:
% Done:

0%

Estimated time:
Affected versions:
Needs backport to:
Affected hardware:
Affected OS:

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

seabios.log (31.5 KB) seabios.log Iru Cai, 05/15/2020 02:53 PM
0005-at-keyboard-timeout.patch (1.09 KB) 0005-at-keyboard-timeout.patch Riku Viitanen, 04/22/2023 12:09 PM
Actions #1

Updated by Paul Menzel over 3 years ago

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.

Actions #2

Updated by Iru Cai over 3 years ago

I've just made a SeaBIOS log (verbosity 7).

Actions #3

Updated by Paul Menzel over 3 years ago

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)

Actions #4

Updated by Riku Viitanen 5 months ago

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

Actions

Also available in: Atom PDF