From 52f39da1f8c7fc23ea5379ce0d4980b9c43b02af Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Fri, 8 Dec 2017 00:57:13 +0000 Subject: [PATCH] Support mounted boot partitions in the installer. This allows the platform layer, for example, to specify that the EFI boot partition should be mounted at /efi and formatted normally with newfs_msdos rather than splatted to from /boot/boot1.efifat. This commit adds only the API for this; actual platform use will come later. --- usr.sbin/bsdinstall/partedit/gpart_ops.c | 154 +++++++++++------- usr.sbin/bsdinstall/partedit/partedit.h | 30 +++- usr.sbin/bsdinstall/partedit/partedit_arm64.c | 2 +- .../bsdinstall/partedit/partedit_generic.c | 2 +- .../bsdinstall/partedit/partedit_powerpc.c | 2 +- .../bsdinstall/partedit/partedit_sparc64.c | 2 +- usr.sbin/bsdinstall/partedit/partedit_x86.c | 2 +- 7 files changed, 122 insertions(+), 72 deletions(-) diff --git a/usr.sbin/bsdinstall/partedit/gpart_ops.c b/usr.sbin/bsdinstall/partedit/gpart_ops.c index 006585573064..e646f3050668 100644 --- a/usr.sbin/bsdinstall/partedit/gpart_ops.c +++ b/usr.sbin/bsdinstall/partedit/gpart_ops.c @@ -191,9 +191,7 @@ newfs_command(const char *fstype, char *command, int use_default) for (i = 0; i < (int)nitems(items); i++) { if (items[i].state == 0) continue; - if (strcmp(items[i].name, "FAT32") == 0) - strcat(command, "-F 32 "); - else if (strcmp(items[i].name, "FAT16") == 0) + if (strcmp(items[i].name, "FAT16") == 0) strcat(command, "-F 16 "); else if (strcmp(items[i].name, "FAT12") == 0) strcat(command, "-F 12 "); @@ -675,6 +673,7 @@ set_default_part_metadata(const char *name, const char *scheme, { struct partition_metadata *md; char *zpool_name = NULL; + const char *default_bootmount = NULL; int i; /* Set part metadata */ @@ -705,8 +704,12 @@ set_default_part_metadata(const char *name, const char *scheme, if (strcmp(type, "freebsd-swap") == 0) mountpoint = "none"; - if (strcmp(type, bootpart_type(scheme)) == 0) - md->bootcode = 1; + if (strcmp(type, bootpart_type(scheme, &default_bootmount)) == 0) { + if (default_bootmount == NULL) + md->bootcode = 1; + else if (mountpoint == NULL || strlen(mountpoint) == 0) + mountpoint = default_bootmount; + } /* VTOC8 needs partcode at the start of partitions */ if (strcmp(scheme, "VTOC8") == 0 && (strcmp(type, "freebsd-ufs") == 0 @@ -886,9 +889,79 @@ gpart_max_free(struct ggeom *geom, intmax_t *npartstart) return (maxsize); } +static size_t +add_boot_partition(struct ggeom *geom, struct gprovider *pp, + const char *scheme, int interactive) +{ + struct gconfig *gc; + struct gprovider *ppi; + int choice; + + /* Check for existing freebsd-boot partition */ + LIST_FOREACH(ppi, &geom->lg_provider, lg_provider) { + struct partition_metadata *md; + const char *bootmount = NULL; + + LIST_FOREACH(gc, &ppi->lg_config, lg_config) + if (strcmp(gc->lg_name, "type") == 0) + break; + if (gc == NULL) + continue; + if (strcmp(gc->lg_val, bootpart_type(scheme, &bootmount)) != 0) + continue; + + /* + * If the boot partition is not mountable and needs partcode, + * but doesn't have it, it doesn't satisfy our requirements. + */ + md = get_part_metadata(ppi->lg_name, 0); + if (bootmount == NULL && (md == NULL || !md->bootcode)) + continue; + + /* If it is mountable, but mounted somewhere else, remount */ + if (bootmount != NULL && md != NULL && md->fstab != NULL + && strlen(md->fstab->fs_file) > 0 + && strcmp(md->fstab->fs_file, bootmount) != 0) + continue; + + /* If it is mountable, but mountpoint is not set, mount it */ + if (bootmount != NULL && md == NULL) + set_default_part_metadata(ppi->lg_name, scheme, + gc->lg_val, bootmount, NULL); + + /* Looks good at this point, no added data needed */ + return (0); + } + + if (interactive) + choice = dialog_yesno("Boot Partition", + "This partition scheme requires a boot partition " + "for the disk to be bootable. Would you like to " + "make one now?", 0, 0); + else + choice = 0; + + if (choice == 0) { /* yes */ + const char *bootmount = NULL; + char sizestr[7]; + + humanize_number(sizestr, 7, + bootpart_size(scheme), "B", HN_AUTOSCALE, + HN_NOSPACE | HN_DECIMAL); + + gpart_create(pp, bootpart_type(scheme, &bootmount), + sizestr, bootmount, NULL, 0); + + return (bootpart_size(scheme)); + } + + return (0); +} + void -gpart_create(struct gprovider *pp, char *default_type, char *default_size, - char *default_mountpoint, char **partname, int interactive) +gpart_create(struct gprovider *pp, const char *default_type, + const char *default_size, const char *default_mountpoint, + char **partname, int interactive) { struct gctl_req *r; struct gconfig *gc; @@ -984,11 +1057,11 @@ gpart_create(struct gprovider *pp, char *default_type, char *default_size, nitems = scheme_supports_labels(scheme) ? 4 : 3; if (default_type != NULL) - items[0].text = default_type; + items[0].text = (char *)default_type; if (default_size != NULL) - items[1].text = default_size; + items[1].text = (char *)default_size; if (default_mountpoint != NULL) - items[2].text = default_mountpoint; + items[2].text = (char *)default_mountpoint; /* Default options */ strncpy(options_fstype, items[0].text, @@ -1105,61 +1178,21 @@ gpart_create(struct gprovider *pp, char *default_type, char *default_size, * the user to add one. */ - /* Check for existing freebsd-boot partition */ - LIST_FOREACH(pp, &geom->lg_provider, lg_provider) { - struct partition_metadata *md; - md = get_part_metadata(pp->lg_name, 0); - if (md == NULL || !md->bootcode) - continue; - LIST_FOREACH(gc, &pp->lg_config, lg_config) - if (strcmp(gc->lg_name, "type") == 0) - break; - if (gc != NULL && strcmp(gc->lg_val, - bootpart_type(scheme)) == 0) - break; - } - - /* If there isn't one, and we need one, ask */ if ((strcmp(items[0].text, "freebsd") == 0 || - strcmp(items[2].text, "/") == 0) && bootpart_size(scheme) > 0 && - pp == NULL) { - if (interactive) - choice = dialog_yesno("Boot Partition", - "This partition scheme requires a boot partition " - "for the disk to be bootable. Would you like to " - "make one now?", 0, 0); - else - choice = 0; + strcmp(items[2].text, "/") == 0) && bootpart_size(scheme) > 0) { + size_t bytes = add_boot_partition(geom, pp, scheme, + interactive); - if (choice == 0) { /* yes */ - r = gctl_get_handle(); - gctl_ro_param(r, "class", -1, "PART"); - gctl_ro_param(r, "arg0", -1, geom->lg_name); - gctl_ro_param(r, "flags", -1, GPART_FLAGS); - gctl_ro_param(r, "verb", -1, "add"); - gctl_ro_param(r, "type", -1, bootpart_type(scheme)); - snprintf(sizestr, sizeof(sizestr), "%jd", - bootpart_size(scheme) / sector); - gctl_ro_param(r, "size", -1, sizestr); - snprintf(startstr, sizeof(startstr), "%jd", firstfree); - gctl_ro_param(r, "start", -1, startstr); - gctl_rw_param(r, "output", sizeof(output), output); - errstr = gctl_issue(r); - if (errstr != NULL && errstr[0] != '\0') - gpart_show_error("Error", NULL, errstr); - gctl_free(r); - - get_part_metadata(strtok(output, " "), 1)->bootcode = 1; - - /* Now adjust the part we are really adding forward */ - firstfree += bootpart_size(scheme) / sector; - size -= (bootpart_size(scheme) + stripe)/sector; + /* Now adjust the part we are really adding forward */ + if (bytes > 0) { + firstfree += bytes / sector; + size -= (bytes + stripe)/sector; if (stripe > 0 && (firstfree*sector % stripe) != 0) firstfree += (stripe - ((firstfree*sector) % stripe)) / sector; } } - + r = gctl_get_handle(); gctl_ro_param(r, "class", -1, "PART"); gctl_ro_param(r, "arg0", -1, geom->lg_name); @@ -1197,9 +1230,8 @@ gpart_create(struct gprovider *pp, char *default_type, char *default_size, gctl_issue(r); /* Error usually expected and non-fatal */ gctl_free(r); - if (strcmp(items[0].text, bootpart_type(scheme)) == 0) - get_part_metadata(newpartname, 1)->bootcode = 1; - else if (strcmp(items[0].text, "freebsd") == 0) + + if (strcmp(items[0].text, "freebsd") == 0) gpart_partition(newpartname, "BSD"); else set_default_part_metadata(newpartname, scheme, diff --git a/usr.sbin/bsdinstall/partedit/partedit.h b/usr.sbin/bsdinstall/partedit/partedit.h index d25b730a6fb5..1dccc653aea1 100644 --- a/usr.sbin/bsdinstall/partedit/partedit.h +++ b/usr.sbin/bsdinstall/partedit/partedit.h @@ -65,8 +65,9 @@ int wizard_makeparts(struct gmesh *mesh, const char *disk, const char *fstype, void gpart_delete(struct gprovider *pp); void gpart_destroy(struct ggeom *lg_geom); void gpart_edit(struct gprovider *pp); -void gpart_create(struct gprovider *pp, char *default_type, char *default_size, - char *default_mountpoint, char **output, int interactive); +void gpart_create(struct gprovider *pp, const char *default_type, + const char *default_size, const char *default_mountpoint, + char **output, int interactive); intmax_t gpart_max_free(struct ggeom *gp, intmax_t *start); void gpart_revert(struct gprovider *pp); void gpart_revert_all(struct gmesh *mesh); @@ -78,12 +79,29 @@ void gpart_set_root(const char *lg_name, const char *attribute); const char *choose_part_type(const char *def_scheme); /* machine-dependent bootability checks */ -const char *default_scheme(void); -int is_scheme_bootable(const char *scheme); -int is_fs_bootable(const char *scheme, const char *fs); +const char *default_scheme(void); /* Default partition scheme */ +int is_scheme_bootable(const char *scheme); /* Non-zero if scheme boots */ +int is_fs_bootable(const char *scheme, const char *fs); /* Ditto if FS boots */ + +/* Size of boot partition in bytes. Zero if no boot partition */ size_t bootpart_size(const char *scheme); -const char *bootpart_type(const char *scheme); + +/* + * Type and mountpoint of boot partition for given scheme. If boot partition + * should not be mounted, set mountpoint to NULL or leave it unchanged. + * Note that mountpoint non-NULL implies partcode_path() will be ignored. + * Do *NOT* set both! + */ +const char *bootpart_type(const char *scheme, const char **mountpoint); + +/* Path to bootcode that goes in the scheme (e.g. disk MBR). NULL if none */ const char *bootcode_path(const char *scheme); + +/* + * Path to boot blocks to be dd'ed into the partition suggested by bootpart_* + * for the given scheme and root filesystem type. If the boot partition should + * be mounted rather than dd'ed to, return NULL here. + */ const char *partcode_path(const char *scheme, const char *fs_type); #endif diff --git a/usr.sbin/bsdinstall/partedit/partedit_arm64.c b/usr.sbin/bsdinstall/partedit/partedit_arm64.c index 7fe784d5c6d1..b226c7cc1474 100644 --- a/usr.sbin/bsdinstall/partedit/partedit_arm64.c +++ b/usr.sbin/bsdinstall/partedit/partedit_arm64.c @@ -77,7 +77,7 @@ bootpart_size(const char *scheme) } const char * -bootpart_type(const char *scheme) +bootpart_type(const char *scheme, const char **mountpoint) { /* Only EFI is supported as boot partition */ diff --git a/usr.sbin/bsdinstall/partedit/partedit_generic.c b/usr.sbin/bsdinstall/partedit/partedit_generic.c index b83ceee7d5f3..e25784592a9b 100644 --- a/usr.sbin/bsdinstall/partedit/partedit_generic.c +++ b/usr.sbin/bsdinstall/partedit/partedit_generic.c @@ -65,7 +65,7 @@ bootpart_size(const char *part_type) { } const char * -bootpart_type(const char *scheme) { +bootpart_type(const char *scheme, const char **mountpoint) { return ("freebsd-boot"); } diff --git a/usr.sbin/bsdinstall/partedit/partedit_powerpc.c b/usr.sbin/bsdinstall/partedit/partedit_powerpc.c index b3928a8856a4..c74c9354c19f 100644 --- a/usr.sbin/bsdinstall/partedit/partedit_powerpc.c +++ b/usr.sbin/bsdinstall/partedit/partedit_powerpc.c @@ -92,7 +92,7 @@ bootpart_size(const char *part_type) { } const char * -bootpart_type(const char *scheme) { +bootpart_type(const char *scheme, const char **mountpoint) { size_t platlen = sizeof(platform); if (strlen(platform) == 0) sysctlbyname("hw.platform", platform, &platlen, NULL, -1); diff --git a/usr.sbin/bsdinstall/partedit/partedit_sparc64.c b/usr.sbin/bsdinstall/partedit/partedit_sparc64.c index ab943ae71e46..514c0e9ffd1d 100644 --- a/usr.sbin/bsdinstall/partedit/partedit_sparc64.c +++ b/usr.sbin/bsdinstall/partedit/partedit_sparc64.c @@ -61,7 +61,7 @@ bootpart_size(const char *part_type) { } const char * -bootpart_type(const char *scheme) { +bootpart_type(const char *scheme, const char **mountpoint) { return ("freebsd-boot"); } diff --git a/usr.sbin/bsdinstall/partedit/partedit_x86.c b/usr.sbin/bsdinstall/partedit/partedit_x86.c index 019753155d59..7e88f0a1b856 100644 --- a/usr.sbin/bsdinstall/partedit/partedit_x86.c +++ b/usr.sbin/bsdinstall/partedit/partedit_x86.c @@ -111,7 +111,7 @@ bootpart_size(const char *scheme) } const char * -bootpart_type(const char *scheme) +bootpart_type(const char *scheme, const char **mountpoint) { if (strcmp(x86_bootmethod(), "UEFI") == 0)