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.

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