If you boot efiboot via PXE and at the prompt enter a different boot
device, e.g.

  boot> boot sd0a:/bsd

then efiboot will pretend to honor this

  booting sd0a:/bsd: ...

but in fact ignore the device and boot from TFTP instead.


In the MI part of the boot loader, open() calls devopen(), which
picks the right device from the MD devsw[] table in conf.c.  open()
will then try the xxx_open() routines from the file_system[] table
until one succeeds.  This assumes that devices and filesystems are
entirely orthogonal, which is a bit iffy since the TFTP and disk
code are independent.  tftp_open() succeeds "on" a disk device that
it never looks at, resulting in the bug above.

The patch below
(1) adds a check to tftp_open() that we are actually opening a TFTP
    device;
(2) clears the bootmac variable in devopen() for non-TFTP devices,
    to prevent the kernel from going into netboot mode.  (Woe, where
    is my root NFS?)

Tested with arm64 BOOTAA64.EFI and amd64 BOOTX64.EFI.
The arm64 code can be copied verbatim to armv7.  Not done below,
and not tested for lack of hardware.

amd64/i386 pxeboot already solves this problem with a slightly
different approach.  It has an MD version of open() that allows
devopen() to directly set the specific file_system[] entry to be
used.  We could pull this modification to open() into the MI code,
but the contortions in devopen() won't get any prettier.


Opinions?
OKs (including dup'ing the arm64 code to armv7)?


Index: sys/arch/arm64/stand/efiboot/efiboot.c
===================================================================
RCS file: /cvs/src/sys/arch/arm64/stand/efiboot/efiboot.c,v
retrieving revision 1.22
diff -u -p -r1.22 efiboot.c
--- sys/arch/arm64/stand/efiboot/efiboot.c      31 Jan 2019 14:35:06 -0000      
1.22
+++ sys/arch/arm64/stand/efiboot/efiboot.c      24 Apr 2019 15:35:51 -0000
@@ -749,6 +749,14 @@ devopen(struct open_file *f, const char 
        dp = &devsw[dev];
        f->f_dev = dp;
 
+       if (strcmp("tftp", dp->dv_name)) {
+               /*
+                * Clear bootmac, to signal that we loaded this file from a
+                * non-network device.
+                */
+               bootmac = NULL;
+       }
+
        return (*dp->dv_open)(f, unit, part);
 }
 
Index: sys/arch/arm64/stand/efiboot/efipxe.c
===================================================================
RCS file: /cvs/src/sys/arch/arm64/stand/efiboot/efipxe.c,v
retrieving revision 1.4
diff -u -p -r1.4 efipxe.c
--- sys/arch/arm64/stand/efiboot/efipxe.c       31 Mar 2018 17:43:53 -0000      
1.4
+++ sys/arch/arm64/stand/efiboot/efipxe.c       24 Apr 2019 15:00:39 -0000
@@ -157,6 +157,9 @@ mtftp_open(char *path, struct open_file 
        EFI_STATUS status;
        UINT64 size;
 
+       if (strcmp("tftp", f->f_dev->dv_name))
+               return ENXIO;
+
        if (PXE == NULL)
                return ENXIO;
 
@@ -295,6 +298,9 @@ mtftp_readdir(struct open_file *f, char 
 int
 efitftp_open(char *path, struct open_file *f)
 {
+       if (strcmp("tftp", f->f_dev->dv_name))
+               return ENXIO;
+
        if (NET == NULL || PXE == NULL)
                return ENXIO;
 
Index: sys/arch/amd64/stand/efiboot/efipxe.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/stand/efiboot/efipxe.c,v
retrieving revision 1.3
diff -u -p -r1.3 efipxe.c
--- sys/arch/amd64/stand/efiboot/efipxe.c       30 Jan 2018 20:19:06 -0000      
1.3
+++ sys/arch/amd64/stand/efiboot/efipxe.c       24 Apr 2019 19:33:06 -0000
@@ -127,6 +127,9 @@ tftp_open(char *path, struct open_file *
        EFI_STATUS status;
        UINT64 size;
 
+       if (strcmp("TFTP", f->f_dev->dv_name))
+               return ENXIO;
+
        if (PXE == NULL)
                return ENXIO;
 
Index: sys/arch/amd64/stand/libsa/dev_i386.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/stand/libsa/dev_i386.c,v
retrieving revision 1.21
diff -u -p -r1.21 dev_i386.c
--- sys/arch/amd64/stand/libsa/dev_i386.c       25 Nov 2017 19:02:07 -0000      
1.21
+++ sys/arch/amd64/stand/libsa/dev_i386.c       24 Apr 2019 19:40:47 -0000
@@ -78,6 +78,16 @@ devopen(struct open_file *f, const char 
 #endif
                if ((rc = (*dp->dv_open)(f, file)) == 0) {
                        f->f_dev = dp;
+#ifdef EFIBOOT
+                       if (strcmp("TFTP", dp->dv_name)) {
+                               /*
+                                * Clear bootmac, to signal that we loaded
+                                * this file from a non-network device.
+                                */
+                               extern char *bootmac;
+                               bootmac = NULL;
+                       }
+#endif
                        return 0;
                }
 #ifdef DEBUG
-- 
Christian "naddy" Weisgerber                          na...@mips.inka.de

Reply via email to