The branch main has been updated by jlduran:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=4007d914e7973bca8ac488ab50aca56964eed90f

commit 4007d914e7973bca8ac488ab50aca56964eed90f
Author:     Jose Luis Duran <[email protected]>
AuthorDate: 2026-07-29 16:11:53 +0000
Commit:     Jose Luis Duran <[email protected]>
CommitDate: 2026-07-29 16:15:15 +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
---
 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);
 }

Reply via email to