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

Reply via email to