/* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "gpt.h" #include "string-util.h" #include "utf8.h" /* Gently push people towards defining GPT type UUIDs for all architectures we know */ #if !defined(GPT_ROOT_NATIVE) || \ !defined(GPT_ROOT_NATIVE_VERITY) || \ !defined(GPT_ROOT_NATIVE_VERITY_SIG) || \ !defined(GPT_USR_NATIVE) || \ !defined(GPT_USR_NATIVE_VERITY) || \ !defined(GPT_USR_NATIVE_VERITY_SIG) #pragma message "Please define GPT partition types for your architecture." #endif #define _GPT_ARCH_SEXTET(arch, name) \ { GPT_ROOT_##arch, "root-" name, ARCHITECTURE_##arch, .is_root = true }, \ { GPT_ROOT_##arch##_VERITY, "root-" name "-verity", ARCHITECTURE_##arch, .is_root_verity = true }, \ { GPT_ROOT_##arch##_VERITY_SIG, "root-" name "-verity-sig", ARCHITECTURE_##arch, .is_root_verity_sig = true }, \ { GPT_USR_##arch, "usr-" name, ARCHITECTURE_##arch, .is_usr = true }, \ { GPT_USR_##arch##_VERITY, "usr-" name "-verity", ARCHITECTURE_##arch, .is_usr_verity = true }, \ { GPT_USR_##arch##_VERITY_SIG, "usr-" name "-verity-sig", ARCHITECTURE_##arch, .is_usr_verity_sig = true } const GptPartitionType gpt_partition_type_table[] = { _GPT_ARCH_SEXTET(ALPHA, "alpha"), _GPT_ARCH_SEXTET(ARC, "arc"), _GPT_ARCH_SEXTET(ARM, "arm"), _GPT_ARCH_SEXTET(ARM64, "arm64"), _GPT_ARCH_SEXTET(IA64, "ia64"), _GPT_ARCH_SEXTET(LOONGARCH64, "loongarch64"), _GPT_ARCH_SEXTET(MIPS_LE, "mips-le"), _GPT_ARCH_SEXTET(MIPS64_LE, "mips64-le"), _GPT_ARCH_SEXTET(PPC, "ppc"), _GPT_ARCH_SEXTET(PPC64, "ppc64"), _GPT_ARCH_SEXTET(PPC64_LE, "ppc64-le"), _GPT_ARCH_SEXTET(RISCV32, "riscv32"), _GPT_ARCH_SEXTET(RISCV64, "riscv64"), _GPT_ARCH_SEXTET(S390, "s390"), _GPT_ARCH_SEXTET(S390X, "s390x"), _GPT_ARCH_SEXTET(TILEGX, "tilegx"), _GPT_ARCH_SEXTET(X86, "x86"), _GPT_ARCH_SEXTET(X86_64, "x86-64"), #ifdef GPT_ROOT_NATIVE { GPT_ROOT_NATIVE, "root", native_architecture(), .is_root = true }, { GPT_ROOT_NATIVE_VERITY, "root-verity", native_architecture(), .is_root_verity = true }, { GPT_ROOT_NATIVE_VERITY_SIG, "root-verity-sig", native_architecture(), .is_root_verity_sig = true }, { GPT_USR_NATIVE, "usr", native_architecture(), .is_usr = true }, { GPT_USR_NATIVE_VERITY, "usr-verity", native_architecture(), .is_usr_verity = true }, { GPT_USR_NATIVE_VERITY_SIG, "usr-verity-sig", native_architecture(), .is_usr_verity_sig = true }, #endif #ifdef GPT_ROOT_SECONDARY _GPT_ARCH_SEXTET(SECONDARY, "secondary"), #endif { GPT_ESP, "esp", _ARCHITECTURE_INVALID }, { GPT_XBOOTLDR, "xbootldr", _ARCHITECTURE_INVALID }, { GPT_SWAP, "swap", _ARCHITECTURE_INVALID }, { GPT_HOME, "home", _ARCHITECTURE_INVALID }, { GPT_SRV, "srv", _ARCHITECTURE_INVALID }, { GPT_VAR, "var", _ARCHITECTURE_INVALID }, { GPT_TMP, "tmp", _ARCHITECTURE_INVALID }, { GPT_USER_HOME, "user-home", _ARCHITECTURE_INVALID }, { GPT_LINUX_GENERIC, "linux-generic", _ARCHITECTURE_INVALID }, {} }; 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; return NULL; } const char *gpt_partition_type_uuid_to_string(sd_id128_t id) { const GptPartitionType *pt; pt = gpt_partition_type_find_by_uuid(id); if (!pt) return NULL; return pt->name; } const char *gpt_partition_type_uuid_to_string_harder( sd_id128_t id, char buffer[static SD_ID128_UUID_STRING_MAX]) { const char *s; assert(buffer); s = gpt_partition_type_uuid_to_string(id); if (s) return s; return sd_id128_to_uuid_string(id, buffer); } int gpt_partition_type_uuid_from_string(const char *s, sd_id128_t *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)) { if (ret) *ret = gpt_partition_type_table[i].uuid; return 0; } return sd_id128_from_string(s, ret); } Architecture gpt_partition_type_uuid_to_arch(sd_id128_t id) { const GptPartitionType *pt; pt = gpt_partition_type_find_by_uuid(id); if (!pt) return _ARCHITECTURE_INVALID; return pt->arch; } int gpt_partition_label_valid(const char *s) { _cleanup_free_ char16_t *recoded = NULL; recoded = utf8_to_utf16(s, strlen(s)); if (!recoded) return -ENOMEM; return char16_strlen(recoded) <= GPT_LABEL_MAX; } static GptPartitionType gpt_partition_type_from_uuid(sd_id128_t id) { const GptPartitionType *pt; pt = gpt_partition_type_find_by_uuid(id); if (pt) return *pt; return (GptPartitionType) { .uuid = id, .arch = _ARCHITECTURE_INVALID }; } bool gpt_partition_type_is_root(sd_id128_t id) { return gpt_partition_type_from_uuid(id).is_root; } bool gpt_partition_type_is_root_verity(sd_id128_t id) { return gpt_partition_type_from_uuid(id).is_root_verity; } bool gpt_partition_type_is_root_verity_sig(sd_id128_t id) { return gpt_partition_type_from_uuid(id).is_root_verity_sig; } bool gpt_partition_type_is_usr(sd_id128_t id) { return gpt_partition_type_from_uuid(id).is_usr; } bool gpt_partition_type_is_usr_verity(sd_id128_t id) { return gpt_partition_type_from_uuid(id).is_usr_verity; } bool gpt_partition_type_is_usr_verity_sig(sd_id128_t id) { return gpt_partition_type_from_uuid(id).is_usr_verity_sig; } bool gpt_partition_type_knows_read_only(sd_id128_t id) { return gpt_partition_type_is_root(id) || gpt_partition_type_is_usr(id) || sd_id128_in_set(id, GPT_HOME, GPT_SRV, GPT_VAR, GPT_TMP, GPT_XBOOTLDR) || gpt_partition_type_is_root_verity(id) || /* pretty much implied, but let's set the bit to make things really clear */ gpt_partition_type_is_usr_verity(id); /* ditto */ } bool gpt_partition_type_knows_growfs(sd_id128_t id) { return gpt_partition_type_is_root(id) || gpt_partition_type_is_usr(id) || sd_id128_in_set(id, GPT_HOME, GPT_SRV, GPT_VAR, GPT_TMP, GPT_XBOOTLDR); } bool gpt_partition_type_knows_no_auto(sd_id128_t id) { return gpt_partition_type_is_root(id) || gpt_partition_type_is_root_verity(id) || gpt_partition_type_is_usr(id) || gpt_partition_type_is_usr_verity(id) || sd_id128_in_set(id, GPT_HOME, GPT_SRV, GPT_VAR, GPT_TMP, GPT_XBOOTLDR, GPT_SWAP); }