Add a “skip_dsn” option to g_part's bootcode verb to prevent g_part_mbr

from setting the volume serial number.  This unbreaks older boot blocks
that don't support serial numbers, and allows boot0cfg to set the serial
number itself if requested by the user.

Submitted by:	lev@, yuripv@
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D17386
This commit is contained in:
Dag-Erling Smørgrav 2018-11-27 14:58:19 +00:00
parent 9361c4ad4e
commit cdd2df880d
6 changed files with 30 additions and 6 deletions

View File

@ -72,6 +72,7 @@ volatile sig_atomic_t undo_restore;
#define GPART_PARAM_BOOTCODE "bootcode"
#define GPART_PARAM_INDEX "index"
#define GPART_PARAM_PARTCODE "partcode"
#define GPART_PARAM_SKIP_DSN "skip_dsn"
static struct gclass *find_class(struct gmesh *, const char *);
static struct ggeom * find_geom(struct gclass *, const char *);
@ -115,8 +116,9 @@ struct g_command PUBSYM(class_commands)[] = {
{ 'p', GPART_PARAM_PARTCODE, G_VAL_OPTIONAL, G_TYPE_STRING },
{ 'i', GPART_PARAM_INDEX, G_VAL_OPTIONAL, G_TYPE_NUMBER },
{ 'f', "flags", GPART_FLAGS, G_TYPE_STRING },
{ 'N', GPART_PARAM_SKIP_DSN, NULL, G_TYPE_BOOL },
G_OPT_SENTINEL },
"[-b bootcode] [-p partcode -i index] [-f flags] geom"
"[-N] [-b bootcode] [-p partcode -i index] [-f flags] geom"
},
{ "commit", 0, gpart_issue, G_NULL_OPTS,
"geom"

View File

@ -49,6 +49,7 @@
.\" ==== BOOTCODE ====
.Nm
.Cm bootcode
.Op Fl N
.Op Fl b Ar bootcode
.Op Fl p Ar partcode Fl i Ar index
.Op Fl f Ar flags
@ -214,6 +215,14 @@ The
.Cm bootcode
command accepts these options:
.Bl -tag -width 10n
.It Fl N
Don't preserve the Volume Serial Number for MBR.
MBR bootcode contains Volume Serial Number by default, and
.Nm
tries to preserve it when installing new bootstrap code.
This option allows to skip the preservation to help with some versions of
.Xr boot0 8
that don't support Volume Serial Number.
.It Fl b Ar bootcode
Embed bootstrap code from the file
.Ar bootcode

View File

@ -1627,6 +1627,7 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
if (!strcmp(verb, "bootcode")) {
ctlreq = G_PART_CTL_BOOTCODE;
mparms |= G_PART_PARM_GEOM | G_PART_PARM_BOOTCODE;
oparms |= G_PART_PARM_SKIP_DSN;
}
break;
case 'c':
@ -1744,6 +1745,8 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
parm = G_PART_PARM_SIZE;
else if (!strcmp(ap->name, "start"))
parm = G_PART_PARM_START;
else if (!strcmp(ap->name, "skip_dsn"))
parm = G_PART_PARM_SKIP_DSN;
break;
case 't':
if (!strcmp(ap->name, "type"))
@ -1804,6 +1807,10 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
case G_PART_PARM_SIZE:
error = g_part_parm_quad(req, ap->name, &gpp.gpp_size);
break;
case G_PART_PARM_SKIP_DSN:
error = g_part_parm_uint32(req, ap->name,
&gpp.gpp_skip_dsn);
break;
case G_PART_PARM_START:
error = g_part_parm_quad(req, ap->name,
&gpp.gpp_start);

View File

@ -202,6 +202,7 @@ enum g_part_ctl {
#define G_PART_PARM_BOOTCODE 0x1000
#define G_PART_PARM_ATTRIB 0x2000
#define G_PART_PARM_FORCE 0x4000
#define G_PART_PARM_SKIP_DSN 0x8000
struct g_part_parms {
unsigned int gpp_parms;
@ -220,6 +221,7 @@ struct g_part_parms {
unsigned int gpp_codesize;
const char *gpp_attrib;
unsigned int gpp_force;
unsigned int gpp_skip_dsn;
};
void g_part_geometry_heads(off_t, u_int, off_t *, u_int *);

View File

@ -274,7 +274,7 @@ g_part_mbr_bootcode(struct g_part_table *basetable, struct g_part_parms *gpp)
table = (struct g_part_mbr_table *)basetable;
dsn = *(uint32_t *)(table->mbr + DOSDSNOFF);
bcopy(gpp->gpp_codeptr, table->mbr, DOSPARTOFF);
if (dsn != 0)
if (dsn != 0 && !gpp->gpp_skip_dsn)
*(uint32_t *)(table->mbr + DOSDSNOFF) = dsn;
return (0);
}

View File

@ -100,7 +100,7 @@ static const char fmt1[] = "%d 0x%02x %4u:%3u:%2u 0x%02x"
static int geom_class_available(const char *);
static int read_mbr(const char *, u_int8_t **, int);
static void write_mbr(const char *, int, u_int8_t *, int);
static void write_mbr(const char *, int, u_int8_t *, int, int);
static void display_mbr(u_int8_t *);
static int boot0version(const u_int8_t *);
static int boot0bs(const u_int8_t *);
@ -200,7 +200,7 @@ main(int argc, char *argv[])
/* save the existing MBR if we are asked to do so */
if (fpath)
write_mbr(fpath, O_CREAT | O_TRUNC, mbr, mbr_size);
write_mbr(fpath, O_CREAT | O_TRUNC, mbr, mbr_size, 0);
/*
* If we are installing the boot loader, read it from disk and copy the
@ -256,7 +256,7 @@ main(int argc, char *argv[])
}
/* write the MBR back to disk */
if (up)
write_mbr(disk, 0, boot0, boot0_size);
write_mbr(disk, 0, boot0, boot0_size, vol_id[4] || b0_ver == 1);
/* display the MBR */
if (v_flag)
@ -372,7 +372,8 @@ geom_class_available(const char *name)
* Write out the mbr to the specified file.
*/
static void
write_mbr(const char *fname, int flags, u_int8_t *mbr, int mbr_size)
write_mbr(const char *fname, int flags, u_int8_t *mbr, int mbr_size,
int disable_dsn)
{
struct gctl_req *grq;
const char *errmsg;
@ -417,6 +418,9 @@ write_mbr(const char *fname, int flags, u_int8_t *mbr, int mbr_size)
gctl_ro_param(grq, "verb", -1, "bootcode");
gctl_ro_param(grq, "bootcode", mbr_size, mbr);
gctl_ro_param(grq, "flags", -1, "C");
if (disable_dsn)
gctl_ro_param(grq, "skip_dsn", sizeof(int),
&disable_dsn);
errmsg = gctl_issue(grq);
if (errmsg != NULL && errmsg[0] != '\0')
errx(1, "GEOM_PART: write bootcode to %s failed: %s",