summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorTobias Heider <tobhe@cvs.openbsd.org>2022-11-22 09:53:47 +0000
committerTobias Heider <tobhe@cvs.openbsd.org>2022-11-22 09:53:47 +0000
commit705fe332af7d0cba407c471a2e269d4b0d1282f0 (patch)
treecd331f8a8f65a58350420de020f2d881a762fd91 /usr.sbin
parenta1ba26d0734029c1e3ffa60a430225686773bb93 (diff)
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@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/installboot/efi_installboot.c62
1 files changed, 60 insertions, 2 deletions
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