Hello, I tried if I could reproduce this issue. (In my setup there is a tftp delivering grub installed by grub-mknetdir)
I could not get it to hang by "terminal_input at_keyboard". But similar to what Jeroen Dekkers described I was not able anymore to enter sane text with the keyboard. It feels like only every ~10th key appears in grub. (In virtualbox, qemu and on a real machine, with grub from testing and/or a build from upstream git.) I could track it down to calls into the PXE stack. By avoiding these calls normal keyboard input is then still possible when having at_keyboard loaded. (Unfortunately being then not able to load anything via network). By using a test function which does only the protected to real mode switch and back without the actual PXE call, I assume the problem is only with the mode switch itself - somehow resetting keyboard states. ------------ Attached patch (against upstream) should help in debugging the problem: - if environment no_nic_poll is set to 1, avoid the problematic PXE call - if environment no_nic_poll is set to 1 make only the switch from protected mode to real and back (and avoids the problematic PXE call) That way the keyboard input stays fluid when using this sequence: set no_nic_poll=1 terminal_input at_keyboard When you now unset the environment the keyboard reacts broken again: unset no_nic_poll (Booting would still be possible if the environment is reset just before downloading any files) ------------ Unfortunately I was not able to reproduce it on a plain from harddisk loaded grub. That leaves a couple of questions open: - have the submitter and commenter also a setup involving PXE? - or do we have 2 or 3 different problems? Kind regards, Bernhard
From 39a1748cd3a4ec9e7f8e6449e3fd131143b77c05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernhard=20=C3=9Cbelacker?= <bernha...@vr-web.de> Date: Thu, 18 Dec 2014 01:26:01 +0100 Subject: Help debugging debian bug #741464 --- grub-core/kern/i386/pc/startup.S | 102 +++++++++++++++++++++++------------- grub-core/net/drivers/i386/pc/pxe.c | 7 +++ include/grub/i386/pc/pxe.h | 1 + 3 files changed, 75 insertions(+), 35 deletions(-) diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index 6bb36c6..1fc0011 100644 --- a/grub-core/kern/i386/pc/startup.S +++ b/grub-core/kern/i386/pc/startup.S @@ -159,42 +159,74 @@ FUNCTION(grub_exit) * int grub_pxe_call (int func, void* data, grub_uint32_t pxe_rm_entry); */ FUNCTION(grub_pxe_call) - pushl %ebp - movl %esp, %ebp - pushl %esi - pushl %edi - pushl %ebx - - movl %ecx, %ebx - movl %eax, %ecx - movl %edx, %eax - andl $0xF, %eax - shrl $4, %edx - shll $16, %edx - addl %eax, %edx + pushl %ebp + movl %esp, %ebp + pushl %esi + pushl %edi + pushl %ebx + + movl %ecx, %ebx + movl %eax, %ecx + movl %edx, %eax + andl $0xF, %eax + shrl $4, %edx + shll $16, %edx + addl %eax, %edx + + PROT_TO_REAL + .code16 + + pushl %ebx + pushl %edx + pushw %cx + movw %sp, %bx + lcall *%ss:6(%bx) + cld + addw $10, %sp + movw %ax, %cx + + REAL_TO_PROT + .code32 + + movzwl %cx, %eax + + popl %ebx + popl %edi + popl %esi + popl %ebp + ret - PROT_TO_REAL - .code16 - - pushl %ebx - pushl %edx - pushw %cx - movw %sp, %bx - lcall *%ss:6(%bx) - cld - addw $10, %sp - movw %ax, %cx - - REAL_TO_PROT - .code32 - - movzwl %cx, %eax - - popl %ebx - popl %edi - popl %esi - popl %ebp - ret +/* + * int prot_to_real_to_prot (int func, void* data, grub_uint32_t pxe_rm_entry); + */ +FUNCTION(prot_to_real_to_prot) + pushl %ebp + movl %esp, %ebp + pushl %esi + pushl %edi + pushl %ebx + + movl %ecx, %ebx + movl %eax, %ecx + movl %edx, %eax + andl $0xF, %eax + shrl $4, %edx + shll $16, %edx + addl %eax, %edx + + PROT_TO_REAL + .code16 + + REAL_TO_PROT + .code32 + + movzwl %cx, %eax + + popl %ebx + popl %edi + popl %esi + popl %ebp + ret #include "../int.S" diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index e8c0b22..801a34c 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -180,6 +180,13 @@ grub_pxe_recv (struct grub_net_card *dev __attribute__ ((unused))) { grub_memset (isr, 0, sizeof (*isr)); isr->func_flag = GRUB_PXE_ISR_IN_START; + + const char *debug = grub_env_get ("no_nic_poll"); + if (debug && debug[0] >= '2') + prot_to_real_to_prot (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); + if (debug && debug[0] >= '1') + return NULL; + grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); /* Normally according to the specification we should also check that isr->func_flag != GRUB_PXE_ISR_OUT_OURS but unfortunately it diff --git a/include/grub/i386/pc/pxe.h b/include/grub/i386/pc/pxe.h index 66002bc..6b763a3 100644 --- a/include/grub/i386/pc/pxe.h +++ b/include/grub/i386/pc/pxe.h @@ -281,6 +281,7 @@ struct grub_pxenv_unload_stack } GRUB_PACKED; int EXPORT_FUNC(grub_pxe_call) (int func, void * data, grub_uint32_t pxe_rm_entry) __attribute__ ((regparm(3))); +int EXPORT_FUNC(prot_to_real_to_prot) (int func, void * data, grub_uint32_t pxe_rm_entry) __attribute__ ((regparm(3))); extern struct grub_pxe_bangpxe *grub_pxe_pxenv; -- 2.1.3