diff --git a/man/systemd-repart.xml b/man/systemd-repart.xml index c18b2eb754..66c86e701e 100644 --- a/man/systemd-repart.xml +++ b/man/systemd-repart.xml @@ -400,6 +400,34 @@ disks that use a different sector size as the disk on which the image is produced. + + ARCH + + This option allows overriding the architecture used for architecture specific + partition types. For example, if set to arm64 a partition type of + root-x86-64 referenced in repart.d/ drop-ins will be patched + dynamically to refer to root-arm64 instead. Takes one of + alpha, + arc, + arm, + arm64, + ia64, + loongarch64, + mips-le, + mips64-le, + parisc, + ppc, + ppc64, + ppc64-le, + riscv32, + riscv64, + s390, + s390x, + tilegx, + x86 or + x86-64. + + diff --git a/src/partition/repart.c b/src/partition/repart.c index 4fde0a58a5..2e9badfd31 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -144,13 +144,14 @@ static uint32_t arg_tpm2_pcr_mask = UINT32_MAX; static char *arg_tpm2_public_key = NULL; static uint32_t arg_tpm2_public_key_pcr_mask = UINT32_MAX; static bool arg_split = false; -static sd_id128_t *arg_filter_partitions = NULL; +static GptPartitionType *arg_filter_partitions = NULL; static size_t arg_n_filter_partitions = 0; static FilterPartitionsType arg_filter_partitions_type = FILTER_PARTITIONS_NONE; -static sd_id128_t *arg_defer_partitions = NULL; +static GptPartitionType *arg_defer_partitions = NULL; static size_t arg_n_defer_partitions = 0; static uint64_t arg_sector_size = 0; static ImagePolicy *arg_image_policy = NULL; +static Architecture arg_architecture = _ARCHITECTURE_INVALID; STATIC_DESTRUCTOR_REGISTER(arg_root, freep); STATIC_DESTRUCTOR_REGISTER(arg_image, freep); @@ -428,7 +429,7 @@ static bool partition_exclude(const Partition *p) { return false; for (size_t i = 0; i < arg_n_filter_partitions; i++) - if (sd_id128_equal(p->type.uuid, arg_filter_partitions[i])) + if (sd_id128_equal(p->type.uuid, arg_filter_partitions[i].uuid)) return arg_filter_partitions_type == FILTER_PARTITIONS_EXCLUDE; return arg_filter_partitions_type == FILTER_PARTITIONS_INCLUDE; @@ -438,7 +439,7 @@ static bool partition_defer(const Partition *p) { assert(p); for (size_t i = 0; i < arg_n_defer_partitions; i++) - if (sd_id128_equal(p->type.uuid, arg_defer_partitions[i])) + if (sd_id128_equal(p->type.uuid, arg_defer_partitions[i].uuid)) return true; return false; @@ -1180,6 +1181,9 @@ static int config_parse_type( if (r < 0) return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse partition type: %s", rvalue); + if (arg_architecture >= 0) + *type = gpt_partition_type_override_architecture(*type, arg_architecture); + return 0; } @@ -5766,7 +5770,7 @@ static int context_minimize(Context *context) { return 0; } -static int parse_partition_types(const char *p, sd_id128_t **partitions, size_t *n_partitions) { +static int parse_partition_types(const char *p, GptPartitionType **partitions, size_t *n_partitions) { int r; assert(partitions); @@ -5789,7 +5793,7 @@ static int parse_partition_types(const char *p, sd_id128_t **partitions, size_t if (!GREEDY_REALLOC(*partitions, *n_partitions + 1)) return log_oom(); - (*partitions)[(*n_partitions)++] = type.uuid; + (*partitions)[(*n_partitions)++] = type; } return 0; @@ -5847,6 +5851,7 @@ static int help(void) { " Take partitions of the specified types into account\n" " but don't populate them yet\n" " --sector-size=SIZE Set the logical sector size for the image\n" + " --architecture=ARCH Set the generic architecture for the image\n" "\nSee the %s for details.\n", program_invocation_short_name, ansi_highlight(), @@ -5888,6 +5893,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_DEFER_PARTITIONS, ARG_SECTOR_SIZE, ARG_SKIP_PARTITIONS, + ARG_ARCHITECTURE, }; static const struct option options[] = { @@ -5920,6 +5926,7 @@ static int parse_argv(int argc, char *argv[]) { { "exclude-partitions", required_argument, NULL, ARG_EXCLUDE_PARTITIONS }, { "defer-partitions", required_argument, NULL, ARG_DEFER_PARTITIONS }, { "sector-size", required_argument, NULL, ARG_SECTOR_SIZE }, + { "architecture", required_argument, NULL, ARG_ARCHITECTURE }, {} }; @@ -6220,6 +6227,14 @@ static int parse_argv(int argc, char *argv[]) { break; + case ARG_ARCHITECTURE: + r = architecture_from_string(optarg); + if (r < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid architecture '%s'", optarg); + + arg_architecture = r; + break; + case '?': return -EINVAL; @@ -6283,6 +6298,14 @@ static int parse_argv(int argc, char *argv[]) { if (arg_pretty < 0 && isatty(STDOUT_FILENO)) arg_pretty = true; + if (arg_architecture >= 0) { + FOREACH_ARRAY(p, arg_filter_partitions, arg_n_filter_partitions) + *p = gpt_partition_type_override_architecture(*p, arg_architecture); + + FOREACH_ARRAY(p, arg_defer_partitions, arg_n_defer_partitions) + *p = gpt_partition_type_override_architecture(*p, arg_architecture); + } + return 1; } diff --git a/src/shared/gpt.c b/src/shared/gpt.c index adf7325704..dd96261888 100644 --- a/src/shared/gpt.c +++ b/src/shared/gpt.c @@ -168,12 +168,12 @@ const GptPartitionType gpt_partition_type_table[] = { { SD_GPT_USR_NATIVE_VERITY_SIG, "usr-verity-sig", native_architecture(), .designator = PARTITION_USR_VERITY_SIG }, #endif #ifdef SD_GPT_ROOT_SECONDARY - { SD_GPT_ROOT_NATIVE, "root-secondary", native_architecture(), .designator = PARTITION_ROOT }, - { SD_GPT_ROOT_NATIVE_VERITY, "root-secondary-verity", native_architecture(), .designator = PARTITION_ROOT_VERITY }, - { SD_GPT_ROOT_NATIVE_VERITY_SIG, "root-secondary-verity-sig", native_architecture(), .designator = PARTITION_ROOT_VERITY_SIG }, - { SD_GPT_USR_NATIVE, "usr-secondary", native_architecture(), .designator = PARTITION_USR }, - { SD_GPT_USR_NATIVE_VERITY, "usr-secondary-verity", native_architecture(), .designator = PARTITION_USR_VERITY }, - { SD_GPT_USR_NATIVE_VERITY_SIG, "usr-secondary-verity-sig", native_architecture(), .designator = PARTITION_USR_VERITY_SIG }, + { SD_GPT_ROOT_SECONDARY, "root-secondary", ARCHITECTURE_SECONDARY, .designator = PARTITION_ROOT }, + { SD_GPT_ROOT_SECONDARY_VERITY, "root-secondary-verity", ARCHITECTURE_SECONDARY, .designator = PARTITION_ROOT_VERITY }, + { SD_GPT_ROOT_SECONDARY_VERITY_SIG, "root-secondary-verity-sig", ARCHITECTURE_SECONDARY, .designator = PARTITION_ROOT_VERITY_SIG }, + { SD_GPT_USR_SECONDARY, "usr-secondary", ARCHITECTURE_SECONDARY, .designator = PARTITION_USR }, + { SD_GPT_USR_SECONDARY_VERITY, "usr-secondary-verity", ARCHITECTURE_SECONDARY, .designator = PARTITION_USR_VERITY }, + { SD_GPT_USR_SECONDARY_VERITY_SIG, "usr-secondary-verity-sig", ARCHITECTURE_SECONDARY, .designator = PARTITION_USR_VERITY_SIG }, #endif { SD_GPT_ESP, "esp", _ARCHITECTURE_INVALID, .designator = PARTITION_ESP }, @@ -190,9 +190,9 @@ const GptPartitionType gpt_partition_type_table[] = { static const GptPartitionType *gpt_partition_type_find_by_uuid(sd_id128_t id) { - for (size_t i = 0; i < ELEMENTSOF(gpt_partition_type_table) - 1; i++) - if (sd_id128_equal(id, gpt_partition_type_table[i].uuid)) - return gpt_partition_type_table + i; + FOREACH_ARRAY(t, gpt_partition_type_table, ELEMENTSOF(gpt_partition_type_table) - 1) + if (sd_id128_equal(id, t->uuid)) + return t; return NULL; } @@ -228,11 +228,11 @@ int gpt_partition_type_from_string(const char *s, GptPartitionType *ret) { assert(s); - for (size_t i = 0; i < ELEMENTSOF(gpt_partition_type_table) - 1; i++) - if (streq(s, gpt_partition_type_table[i].name)) { + FOREACH_ARRAY(t, gpt_partition_type_table, ELEMENTSOF(gpt_partition_type_table) - 1) + if (streq(s, t->name)) { /* Don't return immediately, instead re-resolve by UUID so that we can support * aliases like aarch64 -> arm64 transparently. */ - id = gpt_partition_type_table[i].uuid; + id = t->uuid; break; } @@ -248,6 +248,18 @@ int gpt_partition_type_from_string(const char *s, GptPartitionType *ret) { return 0; } +GptPartitionType gpt_partition_type_override_architecture(GptPartitionType type, Architecture arch) { + assert(arch >= 0); + + FOREACH_ARRAY(t, gpt_partition_type_table, ELEMENTSOF(gpt_partition_type_table) - 1) + if (t->designator == type.designator && t->arch == arch) + return *t; + + /* If we can't find an entry with the same designator and the requested architecture, just return the + * original partition type. */ + return type; +} + Architecture gpt_partition_type_uuid_to_arch(sd_id128_t id) { const GptPartitionType *pt; diff --git a/src/shared/gpt.h b/src/shared/gpt.h index bebfbc6116..8623a8664e 100644 --- a/src/shared/gpt.h +++ b/src/shared/gpt.h @@ -62,6 +62,8 @@ int gpt_partition_label_valid(const char *s); GptPartitionType gpt_partition_type_from_uuid(sd_id128_t id); int gpt_partition_type_from_string(const char *s, GptPartitionType *ret); +GptPartitionType gpt_partition_type_override_architecture(GptPartitionType type, Architecture arch); + const char *gpt_partition_type_mountpoint_nulstr(GptPartitionType type); bool gpt_partition_type_knows_read_only(GptPartitionType type); diff --git a/src/test/test-gpt.c b/src/test/test-gpt.c index 5ad30fab44..fa5923eb27 100644 --- a/src/test/test-gpt.c +++ b/src/test/test-gpt.c @@ -81,4 +81,31 @@ TEST(type_alias_same) { } } +TEST(override_architecture) { + GptPartitionType x, y; + + assert_se(gpt_partition_type_from_string("root-x86-64", &x) >= 0); + assert_se(x.arch == ARCHITECTURE_X86_64); + + assert_se(gpt_partition_type_from_string("root-arm64", &y) >= 0); + assert(y.arch == ARCHITECTURE_ARM64); + + x = gpt_partition_type_override_architecture(x, ARCHITECTURE_ARM64); + assert_se(x.arch == y.arch); + assert_se(x.designator == y.designator); + assert_se(sd_id128_equal(x.uuid, y.uuid)); + assert_se(streq(x.name, y.name)); + + /* If the partition type does not have an architecture, nothing should change. */ + + assert_se(gpt_partition_type_from_string("esp", &x) >= 0); + y = x; + + x = gpt_partition_type_override_architecture(x, ARCHITECTURE_ARM64); + assert_se(x.arch == y.arch); + assert_se(x.designator == y.designator); + assert_se(sd_id128_equal(x.uuid, y.uuid)); + assert_se(streq(x.name, y.name)); +} + DEFINE_TEST_MAIN(LOG_INFO);