> Date: Thu, 17 Mar 2022 11:02:00 +0000
> From: Miod Vallat <[email protected]>
> 
> By default (with no override in /etc/boot.conf), the arm64 boot loader
> will attempt to boot the kernel after a 5 second timeout.
> 
> On the RPi 4b here, it will indeed boot the kernel, but after about 80
> seconds.
> 
> The reason for this delay is that there is logic in the boot code, while
> waiting for keystrokes, to limit the timeout check to "only once every
> 1000 times the console reports no keystroke". That logic was introduced
> almost 23 years ago to cope with some slow i386 BIOses.
> 
> However, when there is no console activity, the EFI routine to check for
> a keystroke will itself wait for about 80 millisecond before returning
> failure, which in turn causes the timeout check to be performed only
> once every 80 seconds. Bummer.
> 
> The following diff introduces a compile-time symbol to reduce the loop
> counter from 1000 to 10, and enables this on arm64. This results in
> accurate timeout processing, and the system correctly boots after 5
> seconds of idleness.
> 
> That change might be needed on some other systems (armv7, riscv64?) as
> well.

This issue has been fixed somewhat recently in U-Boot.  It only
happens if you connect a USB keyboard to the machine.  With the
exception of Apple machines and possibly the Raspberry Pi, I expect
most people to use a serial console on arm64 (and armv7 and riscv64)
machines.  And Apple machines will have a fixed U-Boot.

Note that this bug not only affects the timeout.  It makes loading the
kernel from disk slow as well.  So we probably should patch the U-Boot
version we ship and/or update to U-Boot 2022.04 when it is released in
a few weeks.

It may still be worth doing something like this, but would a middle
groun of making it loop something like a 100 times be an option?


> Index: arch/arm64/stand/efiboot/Makefile
> ===================================================================
> RCS file: /OpenBSD/src/sys/arch/arm64/stand/efiboot/Makefile,v
> retrieving revision 1.15
> diff -u -p -r1.15 Makefile
> --- arch/arm64/stand/efiboot/Makefile 14 Mar 2022 19:09:32 -0000      1.15
> +++ arch/arm64/stand/efiboot/Makefile 17 Mar 2022 10:53:34 -0000
> @@ -49,6 +49,7 @@ CPPFLAGS+=  -I${EFIDIR}/include -I${EFIDI
>  CPPFLAGS+=   -D_STANDALONE
>  CPPFLAGS+=   -DSMALL -DSLOW -DNOBYFOUR -D__INTERNAL_LIBSA_CREAD
>  CPPFLAGS+=   -DNEEDS_HEAP_H -DMDRANDOM -DFWRANDOM
> +CPPFLAGS+=   -DSLOW_CNISCHAR
>  COPTS+=              -Wno-attributes -Wno-format
>  COPTS+=              -ffreestanding -fno-stack-protector
>  COPTS+=              -fshort-wchar -fPIC -fno-builtin
> Index: arch/arm64/stand/efiboot/conf.c
> ===================================================================
> RCS file: /OpenBSD/src/sys/arch/arm64/stand/efiboot/conf.c,v
> retrieving revision 1.36
> diff -u -p -r1.36 conf.c
> --- arch/arm64/stand/efiboot/conf.c   14 Mar 2022 19:09:32 -0000      1.36
> +++ arch/arm64/stand/efiboot/conf.c   17 Mar 2022 10:53:34 -0000
> @@ -46,7 +46,7 @@
>  #include "efipxe.h"
>  #include "softraid_arm64.h"
>  
> -const char version[] = "1.8";
> +const char version[] = "1.9";
>  int  debug = 0;
>  
>  struct fs_ops file_system[] = {
> Index: stand/boot/cmd.c
> ===================================================================
> RCS file: /OpenBSD/src/sys/stand/boot/cmd.c,v
> retrieving revision 1.68
> diff -u -p -r1.68 cmd.c
> --- stand/boot/cmd.c  24 Oct 2021 17:49:19 -0000      1.68
> +++ stand/boot/cmd.c  17 Mar 2022 10:53:35 -0000
> @@ -238,6 +238,18 @@ whatcmd(const struct cmd_table **ct, cha
>       return q;
>  }
>  
> +/*
> + * If there is a timeout, we want to honour it as best as possible, but
> + * the getsecs() call might be expensive, so we don't want to check for
> + * timeout too frequently... unless cnischar() itself takes a long time
> + * to report no activity.
> + */
> +#ifdef SLOW_CNISCHAR
> +#define      TIMEOUT_LOOP    10
> +#else
> +#define      TIMEOUT_LOOP    1000
> +#endif
> +
>  static int
>  readline(char *buf, size_t n, int to)
>  {
> @@ -254,10 +266,9 @@ readline(char *buf, size_t n, int to)
>               if (debug > 2)
>                       printf ("readline: timeout(%d) at %u\n", to, tt);
>  #endif
> -             /* check for timeout expiration less often
> -                (for some very constrained archs) */
> +             /* Check for timeout expiration */
>               while (!cnischar())
> -                     if (!(i++ % 1000) && (getsecs() >= tt))
> +                     if (!(i++ % TIMEOUT_LOOP) && (getsecs() >= tt))
>                               break;
>  
>               if (!cnischar()) {
> 
> 

Reply via email to