git: 15a0a7d525cf - stable/15 - boot0cfg: Also allow a file as a trailing argument

Jose Luis Duran <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.src
Message-ID <6a728344.27817.7d3a8c91__48179.1798070603$1785889622$gmane$org@gitrepo.freebsd.org>
The branch stable/15 has been updated by jlduran:

URL: https://cgit.FreeBSD.org/src/commit/?id=15a0a7d525cf8e306f9f202496f67bee12026660

commit 15a0a7d525cf8e306f9f202496f67bee12026660
Author:     Jose Luis Duran <[email protected]>
AuthorDate: 2026-07-29 16:11:53 +0000
Commit:     Jose Luis Duran <[email protected]>
CommitDate: 2026-08-05 00:25:31 +0000

    boot0cfg: Also allow a file as a trailing argument
    
    Modify the disk check to allow arbitrary files as the trailing argument
    instead of requiring a live GEOM disk provider.
    
    This enables modifying a boot0 binary file in-place before flashing it
    to a disk via gpart bootcode, or using it directly as an argument to
    mkimg's partition specification, as these tools cannot directly adjust
    the parameters of the boot0 boot manager.
    
    Reviewed by:    imp, jhb
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D57310
    
    (cherry picked from commit 4007d914e7973bca8ac488ab50aca56964eed90f)
---
 usr.sbin/boot0cfg/boot0cfg.8 | 32 ++++++++++++++++++++++++++------
 usr.sbin/boot0cfg/boot0cfg.c | 40 ++++++++++++++++++++++++++++++++++------
 2 files changed, 60 insertions(+), 12 deletions(-)

diff --git a/usr.sbin/boot0cfg/boot0cfg.8 b/usr.sbin/boot0cfg/boot0cfg.8
index d2e01ada3552..6688d97c65fb 100644
--- a/usr.sbin/boot0cfg/boot0cfg.8
+++ b/usr.sbin/boot0cfg/boot0cfg.8
@@ -22,7 +22,7 @@
 .\" OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 .\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd October 1, 2013
+.Dd July 29, 2026
 .Dt BOOT0CFG 8
 .Os
 .Sh NAME
@@ -40,7 +40,7 @@
 .Op Fl o Ar options
 .Op Fl s Ar slice
 .Op Fl t Ar ticks
-.Ar disk
+.Ar disk | file
 .Sh DESCRIPTION
 The
 .Fx
@@ -62,9 +62,15 @@ The
 utility optionally installs the
 .Sq boot0
 boot manager on the specified
-.Ar disk ;
+.Ar disk
+or
+.Ar file ;
 and allows various operational parameters to be configured.
 .Pp
+If a file is specified as the target argument, all operations are
+performed entirely in-place.
+This allows for offline payload preparation.
+.Pp
 On PCs, a boot manager typically occupies sector 0 of a disk, which is
 known as the Master Boot Record (MBR).
 The MBR contains both code (to which control is passed by the PC BIOS)
@@ -104,8 +110,10 @@ Specify that a backup copy of the preexisting MBR should be written to
 This file is created if it does not exist, and replaced if it does.
 .It Fl i Ar volume-id
 Specifies a volume-id (in the form XXXX-XXXX) to be saved at location
-0x1b8 in the MBR. This information is sometimes used by NT, XP and Vista
-to identify the disk drive. The option is only compatible with version 2.00
+0x1b8 in the MBR.
+This information is sometimes used by NT, XP and Vista to identify the
+disk drive.
+The option is only compatible with version 2.00
 of the 512-byte boot block.
 .It Fl m Ar mask
 Specify slices to be enabled/disabled, where
@@ -177,6 +185,17 @@ To enable just slices 1 and 3 in the menu:
 .Pp
 .Dl "boot0cfg -m 0x5 ada0"
 .Pp
+Create a copy of
+.Sq boot0
+with only slices 1 and 3 enabled in the menu and install that onto a disk using
+.Xr gpart 8 :
+.Pp
+.Bd -literal -offset indent -compact
+cp /boot/boot0 /boot/boot0.custom
+boot0cfg -m 0x5 /boot/boot0.custom
+gpart bootcode -b /boot/boot0.custom ada0
+.Ed
+.Pp
 To go back to non-interactive booting, use
 .Xr gpart 8
 to install the default MBR:
@@ -199,4 +218,5 @@ Use of the
 .Sq setdrv
 option with an incorrect -d operand may cause the boot0 code
 to write the MBR to the wrong disk, thus trashing its previous
-content.  Be careful.
+content.
+Be careful.
diff --git a/usr.sbin/boot0cfg/boot0cfg.c b/usr.sbin/boot0cfg/boot0cfg.c
index 2a919f0b2f2e..172281172908 100644
--- a/usr.sbin/boot0cfg/boot0cfg.c
+++ b/usr.sbin/boot0cfg/boot0cfg.c
@@ -115,6 +115,7 @@ static int v_flag;
 int
 main(int argc, char *argv[])
 {
+    struct stat sb;
     u_int8_t *mbr, *boot0;
     int boot0_size, mbr_size;
     const char *bpath, *fpath;
@@ -183,9 +184,15 @@ main(int argc, char *argv[])
     argv += optind;
     if (argc != 1)
         usage();
-    disk = g_device_path(*argv);
-    if (disk == NULL)
-        errx(1, "Unable to get providername for %s\n", *argv);
+    if (stat(*argv, &sb) == 0 && S_ISREG(sb.st_mode)) {
+        disk = strdup(*argv);
+        if (disk == NULL)
+            err(1, "strdup");
+    } else {
+        disk = g_device_path(*argv);
+        if (disk == NULL)
+            errx(1, "Unable to get providername for %s\n", *argv);
+    }
     up = B_flag || d_arg != -1 || m_arg != -1 || o_flag || s_arg != -1
 	|| t_arg != -1;
 
@@ -373,6 +380,7 @@ write_mbr(const char *fname, int flags, u_int8_t *mbr, int mbr_size,
     int disable_dsn)
 {
 	struct gctl_req *grq;
+	struct stat sb;
 	const char *errmsg;
 	char *pname;
 	ssize_t n;
@@ -394,20 +402,40 @@ write_mbr(const char *fname, int flags, u_int8_t *mbr, int mbr_size,
 	if (flags != 0)
 		err(1, "can't open file %s to write backup", fname);
 
-	/* Try open it read only. */
+	/*
+	 * Try to open it read only to pass to GEOM,
+	 * or inspect if it's a regular file.
+	 */
 	fd = open(fname, O_RDONLY);
 	if (fd == -1) {
 		warn("error opening %s", fname);
 		return;
 	}
 
+	/*
+	 * If name is a regular file, re-open it in write-only mode
+	 * and write the MBR straight to it.
+	 */
+	if (fstat(fd, &sb) == 0 && S_ISREG(sb.st_mode)) {
+		close(fd);
+		fd = open(fname, O_WRONLY);
+		if (fd == -1)
+			err(1, "can't open %s for writing", fname);
+		n = write(fd, mbr, mbr_size);
+		close(fd);
+		if (n != mbr_size)
+			errx(1, "%s: short write", fname);
+		return;
+	}
+
 	pname = g_providername(fd);
+	close(fd);
 	if (pname == NULL) {
 		warn("error getting providername for %s", fname);
 		return;
 	}
 
-	/* First check that GEOM_PART is available */
+	/* Check that GEOM_PART is available */
 	if (geom_class_available("PART") != 0) {
 		grq = gctl_get_handle();
 		gctl_ro_param(grq, "class", -1, "PART");
@@ -594,6 +622,6 @@ usage(void)
 {
     fprintf(stderr, "%s\n%s\n",
     "usage: boot0cfg [-Bv] [-b boot0] [-d drive] [-f file] [-m mask]",
-    "                [-o options] [-s slice] [-t ticks] disk");
+    "                [-o options] [-s slice] [-t ticks] disk | file");
     exit(1);
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.