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
This commit is contained in:
Jose Luis Duran committed 2026-07-29 16:15:15 +00:00
1 parent 1e39a314d8
commit 4007d914e7
2 files changed
+60 -12

No files matched your search

+26 -6
View File
@@ -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.
+34 -6
View File
@@ -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);
}