On Sat, Nov 19, 2022 at 07:25:52PM +0100, Mark Kettenis wrote:
> > Date: Sat, 19 Nov 2022 18:44:19 +0100
> > From: Tobias Heider <[email protected]>
> >
> > On Sat, Nov 19, 2022 at 06:33:51PM +0100, Mark Kettenis wrote:
> > > > Date: Sat, 19 Nov 2022 18:26:36 +0100
> > > > From: Tobias Heider <[email protected]>
> > > >
> > > > Here is the promised last diff we need to enable Apple M* bootloader
> > > > updates.
> > > >
> > > > With this, installboot(8) will pick up apple-boot.bin from the firmware
> > > > directory and writes it to $ESP/m1n1/boot.bin if both file and target
> > > > directory exist.
> > > > Creation of the m1n1/ directory is expected to happen during the initial
> > > > Asahi Linux EFI environment installation so it is safe to assume it is
> > > > already there when we need it.
> > > >
> > > > Running this on my M2 gives me:
> > > >
> > > > kischt# installboot -v sd0
> > > > Using / as root
> > > > installing bootstrap on /dev/rsd0c
> > > > using first-stage /usr/mdec/BOOTAA64.EFI
> > > > copying /etc/firmware/apple-boot.bin to
> > > > /tmp/installboot.0JSQ0XrWRB/m1n1/boot.bin
> > > > copying /usr/mdec/BOOTAA64.EFI to
> > > > /tmp/installboot.0JSQ0XrWRB/efi/boot/bootaa64.efi
> > > > writing /tmp/installboot.0JSQ0XrWRB/efi/boot/startup.nsh
> > >
> > > Hmm...
> > >
> > > > Index: efi_installboot.c
> > > > ===================================================================
> > > > RCS file: /cvs/src/usr.sbin/installboot/efi_installboot.c,v
> > > > retrieving revision 1.6
> > > > diff -u -p -r1.6 efi_installboot.c
> > > > --- efi_installboot.c 14 Sep 2022 16:43:00 -0000 1.6
> > > > +++ efi_installboot.c 19 Nov 2022 16:45:36 -0000
> > > > @@ -191,6 +191,7 @@ write_filesystem(struct disklabel *dl, c
> > > > struct msdosfs_args args;
> > > > char cmd[60];
> > > > char dst[PATH_MAX];
> > > > + struct stat st;
> > > > char *src;
> > > > size_t mntlen, pathlen, srclen;
> > > > int rslt;
> > > > @@ -245,7 +246,36 @@ write_filesystem(struct disklabel *dl, c
> > > > }
> > > > }
> > > >
> > > > + /* Copy apple-boot firmware to /m1n1/boot.bin if available */
> > > > + src = fileprefix(root, "/etc/firmware/apple-boot.bin");
> > > > + if (src == NULL) {
> > > > + rslt = -1;
> > > > + goto umount;
> > >
> > > Doesn't this mean that if /etc/firmware/apple-boot.bin doesn't exist,
> > > we won't write the OpenBSD bootloader to the filesystem? That would
> > > be wrong.
> > >
> > > So I think the Apple "magic" needs to be done at the end of the
> > > function.
> >
> > That is what I also first thought, but fileprefix() just concats the strings
> > and doesn't actually touch the file system. This is also why I added my own
> > stat() && S_ISDIR() check below to make sure the directory exists.
> >
> > Wit apple-boot manually deleted I get:
> >
> > kischt# installboot -v sd0
> > Using / as root
> > installing bootstrap on /dev/rsd0c
> > using first-stage /usr/mdec/BOOTAA64.EFI
> > copying /usr/mdec/BOOTAA64.EFI to
> > /tmp/installboot.Tm5s4GRaRT/efi/boot/bootaa64.efi
> > writing /tmp/installboot.Tm5s4GRaRT/efi/boot/startup.nsh
>
> Hmm, but it will still fail if the /etc/firmware directory doesn't
> exist under the "root". Which may be the case if you are using the -r
> option?
>
Right, regress also trips over this.
Moving the whole block inside fileprefix() != NULL is not enough since
that would still print the error message. We might have to add our own
check fore $root/etc/firmware, although that duplicates some of the
code in fileprefix().
Index: efi_installboot.c
===================================================================
RCS file: /cvs/src/usr.sbin/installboot/efi_installboot.c,v
retrieving revision 1.7
diff -u -p -r1.7 efi_installboot.c
--- efi_installboot.c 6 Nov 2022 12:33:41 -0000 1.7
+++ efi_installboot.c 19 Nov 2022 19:19:28 -0000
@@ -194,6 +194,8 @@ write_filesystem(struct disklabel *dl, c
struct msdosfs_args args;
char cmd[60];
char dst[PATH_MAX];
+ char fw[PATH_MAX];
+ struct stat st;
char *src;
size_t mntlen, pathlen, srclen;
int rslt;
@@ -248,7 +250,46 @@ write_filesystem(struct disklabel *dl, c
}
}
+ /* Copy apple-boot firmware to /m1n1/boot.bin if available */
+ pathlen = strlen(dst);
+ if (strlcat(dst, "/m1n1", sizeof(dst)) >= sizeof(dst)) {
+ rslt = -1;
+ warn("unable to build /m1n1 path");
+ goto umount;
+ }
+ rslt = snprintf(fw, PATH_MAX, "%s/%s", root, "/etc/firmware");
+ if (rslt < 0 || rslt >= PATH_MAX) {
+ rslt = -1;
+ warn("unable to build /etc/firmware path");
+ goto umount;
+ }
+ if ((stat(fw, &st) == 0) && S_ISDIR(st.st_mode) &&
+ (stat(dst, &st) == 0) && S_ISDIR(st.st_mode)) {
+ src = fileprefix(fw, "/apple-boot.bin");
+ if (src == NULL) {
+ rslt = -1;
+ goto umount;
+ }
+ if (access(src, R_OK) == 0) {
+ if (strlcat(dst, "/boot.bin",
+ sizeof(dst)) >= sizeof(dst)) {
+ rslt = -1;
+ warn("unable to build /m1n1/boot.bin path");
+ goto umount;
+ }
+ if (verbose)
+ fprintf(stderr, "%s %s to %s\n",
+ (nowrite ? "would copy" : "copying"),
+ src, dst);
+ if (!nowrite)
+ rslt = filecopy(src, dst);
+ if (rslt == -1)
+ goto umount;
+ }
+ }
+
/* Create "/efi/boot" directory in <duid>.<part>. */
+ dst[pathlen] = '\0';
if (strlcat(dst, "/efi", sizeof(dst)) >= sizeof(dst)) {
rslt = -1;
warn("unable to build /efi directory");