From: tobhe Date: Tue, 22 Nov 2022 09:53:46 +0000 (+0000) Subject: Copy apple-boot firmware to EFI system partition. This enables automatic X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=8fb3e437d8428eccb1c641743b56d8d8e6ea44d3;p=openbsd Copy apple-boot firmware to EFI system partition. This enables automatic bootloader updates on Apple Silicon computers. We rely on fw_update(8) to place apple-boot.bin in /etc/firmware. installboot(8) will pick it up from there and copy it to $ESP/m1n1/boot.bin, if this directory exists. The m1n1 directory and original boot.bin are created by the Asahi Linux installer as part of the initial UEFI environment. The firmware package was manually tested by many. Regress, installation and upgrade with and without apple-boot.bin tested by me. Feedback and ok kettenis@ kn@ --- diff --git a/usr.sbin/installboot/efi_installboot.c b/usr.sbin/installboot/efi_installboot.c index 77e7130e441..643254fd7df 100644 --- a/usr.sbin/installboot/efi_installboot.c +++ b/usr.sbin/installboot/efi_installboot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: efi_installboot.c,v 1.7 2022/11/06 12:33:41 krw Exp $ */ +/* $OpenBSD: efi_installboot.c,v 1.8 2022/11/22 09:53:46 tobhe Exp $ */ /* $NetBSD: installboot.c,v 1.5 1995/11/17 23:23:50 gwr Exp $ */ /* @@ -70,6 +70,7 @@ static int create_filesystem(struct disklabel *, char); static void write_filesystem(struct disklabel *, char); +static int write_firmware(const char *, const char *); static int findgptefisys(int, struct disklabel *); static int findmbrfat(int, struct disklabel *); @@ -308,7 +309,10 @@ write_filesystem(struct disklabel *dl, char part) goto umount; } - rslt = 0; + dst[mntlen] = '\0'; + rslt = write_firmware(root, dst); + if (rslt == -1) + warnx("unable to write firmware"); umount: dst[mntlen] = '\0'; @@ -327,6 +331,60 @@ rmdir: exit(1); } +static int +write_firmware(const char *root, const char *mnt) +{ + char dst[PATH_MAX]; + char fw[PATH_MAX]; + char *src; + struct stat st; + int rslt; + + strlcpy(dst, mnt, sizeof(dst)); + + /* Skip if no /etc/firmware exists */ + rslt = snprintf(fw, sizeof(fw), "%s/%s", root, "etc/firmware"); + if (rslt < 0 || rslt >= PATH_MAX) { + warnx("unable to build /etc/firmware path"); + return -1; + } + if ((stat(fw, &st) != 0) || !S_ISDIR(st.st_mode)) + return 0; + + /* Copy apple-boot firmware to /m1n1/boot.bin if available */ + src = fileprefix(fw, "/apple-boot.bin"); + if (src == NULL) + return -1; + if (access(src, R_OK) == 0) { + if (strlcat(dst, "/m1n1", sizeof(dst)) >= sizeof(dst)) { + rslt = -1; + warnx("unable to build /m1n1 path"); + goto cleanup; + } + if ((stat(dst, &st) != 0) || !S_ISDIR(st.st_mode)) { + rslt = 0; + goto cleanup; + } + if (strlcat(dst, "/boot.bin", sizeof(dst)) >= sizeof(dst)) { + rslt = -1; + warnx("unable to build /m1n1/boot.bin path"); + goto cleanup; + } + 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 cleanup; + } + rslt = 0; + + cleanup: + free(src); + return rslt; +} + /* * Returns 0 if the MBR with the provided partition array is a GPT protective * MBR, and returns 1 otherwise. A GPT protective MBR would have one and only