1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include "gpt.h"
4 #include "string-util.h"
5 #include "utf8.h"
6 
7 /* Gently push people towards defining GPT type UUIDs for all architectures we know */
8 #if !defined(GPT_ROOT_NATIVE) ||                                        \
9         !defined(GPT_ROOT_NATIVE_VERITY) ||                             \
10         !defined(GPT_ROOT_NATIVE_VERITY_SIG) ||                         \
11         !defined(GPT_USR_NATIVE) ||                                     \
12         !defined(GPT_USR_NATIVE_VERITY) ||                              \
13         !defined(GPT_USR_NATIVE_VERITY_SIG)
14 #pragma message "Please define GPT partition types for your architecture."
15 #endif
16 
17 #define _GPT_ARCH_SEXTET(arch, name)                                   \
18         { GPT_ROOT_##arch,              "root-" name,               ARCHITECTURE_##arch, .is_root = true            },  \
19         { GPT_ROOT_##arch##_VERITY,     "root-" name "-verity",     ARCHITECTURE_##arch, .is_root_verity = true     },  \
20         { GPT_ROOT_##arch##_VERITY_SIG, "root-" name "-verity-sig", ARCHITECTURE_##arch, .is_root_verity_sig = true },  \
21         { GPT_USR_##arch,               "usr-" name,                ARCHITECTURE_##arch, .is_usr = true             },  \
22         { GPT_USR_##arch##_VERITY,      "usr-" name "-verity",      ARCHITECTURE_##arch, .is_usr_verity = true      },  \
23         { GPT_USR_##arch##_VERITY_SIG,  "usr-" name "-verity-sig",  ARCHITECTURE_##arch, .is_usr_verity_sig = true  }
24 
25 const GptPartitionType gpt_partition_type_table[] = {
26         _GPT_ARCH_SEXTET(ALPHA,       "alpha"),
27         _GPT_ARCH_SEXTET(ARC,         "arc"),
28         _GPT_ARCH_SEXTET(ARM,         "arm"),
29         _GPT_ARCH_SEXTET(ARM64,       "arm64"),
30         _GPT_ARCH_SEXTET(IA64,        "ia64"),
31         _GPT_ARCH_SEXTET(LOONGARCH64, "loongarch64"),
32         _GPT_ARCH_SEXTET(MIPS_LE,     "mips-le"),
33         _GPT_ARCH_SEXTET(MIPS64_LE,   "mips64-le"),
34         _GPT_ARCH_SEXTET(PPC,         "ppc"),
35         _GPT_ARCH_SEXTET(PPC64,       "ppc64"),
36         _GPT_ARCH_SEXTET(PPC64_LE,     "ppc64-le"),
37         _GPT_ARCH_SEXTET(RISCV32,     "riscv32"),
38         _GPT_ARCH_SEXTET(RISCV64,     "riscv64"),
39         _GPT_ARCH_SEXTET(S390,        "s390"),
40         _GPT_ARCH_SEXTET(S390X,       "s390x"),
41         _GPT_ARCH_SEXTET(TILEGX,      "tilegx"),
42         _GPT_ARCH_SEXTET(X86,         "x86"),
43         _GPT_ARCH_SEXTET(X86_64,      "x86-64"),
44 #ifdef GPT_ROOT_NATIVE
45         { GPT_ROOT_NATIVE,            "root",            native_architecture(), .is_root = true            },
46         { GPT_ROOT_NATIVE_VERITY,     "root-verity",     native_architecture(), .is_root_verity = true     },
47         { GPT_ROOT_NATIVE_VERITY_SIG, "root-verity-sig", native_architecture(), .is_root_verity_sig = true },
48         { GPT_USR_NATIVE,             "usr",             native_architecture(), .is_usr = true             },
49         { GPT_USR_NATIVE_VERITY,      "usr-verity",      native_architecture(), .is_usr_verity = true      },
50         { GPT_USR_NATIVE_VERITY_SIG,  "usr-verity-sig",  native_architecture(), .is_usr_verity_sig = true  },
51 #endif
52 #ifdef GPT_ROOT_SECONDARY
53         _GPT_ARCH_SEXTET(SECONDARY,   "secondary"),
54 #endif
55 
56         { GPT_ESP,                    "esp",           _ARCHITECTURE_INVALID },
57         { GPT_XBOOTLDR,               "xbootldr",      _ARCHITECTURE_INVALID },
58         { GPT_SWAP,                   "swap",          _ARCHITECTURE_INVALID },
59         { GPT_HOME,                   "home",          _ARCHITECTURE_INVALID },
60         { GPT_SRV,                    "srv",           _ARCHITECTURE_INVALID },
61         { GPT_VAR,                    "var",           _ARCHITECTURE_INVALID },
62         { GPT_TMP,                    "tmp",           _ARCHITECTURE_INVALID },
63         { GPT_USER_HOME,              "user-home",     _ARCHITECTURE_INVALID },
64         { GPT_LINUX_GENERIC,          "linux-generic", _ARCHITECTURE_INVALID },
65         {}
66 };
67 
gpt_partition_type_find_by_uuid(sd_id128_t id)68 static const GptPartitionType *gpt_partition_type_find_by_uuid(sd_id128_t id) {
69 
70         for (size_t i = 0; i < ELEMENTSOF(gpt_partition_type_table) - 1; i++)
71                 if (sd_id128_equal(id, gpt_partition_type_table[i].uuid))
72                         return gpt_partition_type_table + i;
73 
74         return NULL;
75 }
76 
gpt_partition_type_uuid_to_string(sd_id128_t id)77 const char *gpt_partition_type_uuid_to_string(sd_id128_t id) {
78         const GptPartitionType *pt;
79 
80         pt = gpt_partition_type_find_by_uuid(id);
81         if (!pt)
82                 return NULL;
83 
84         return pt->name;
85 }
86 
gpt_partition_type_uuid_to_string_harder(sd_id128_t id,char buffer[static SD_ID128_UUID_STRING_MAX])87 const char *gpt_partition_type_uuid_to_string_harder(
88                 sd_id128_t id,
89                 char buffer[static SD_ID128_UUID_STRING_MAX]) {
90 
91         const char *s;
92 
93         assert(buffer);
94 
95         s = gpt_partition_type_uuid_to_string(id);
96         if (s)
97                 return s;
98 
99         return sd_id128_to_uuid_string(id, buffer);
100 }
101 
gpt_partition_type_uuid_from_string(const char * s,sd_id128_t * ret)102 int gpt_partition_type_uuid_from_string(const char *s, sd_id128_t *ret) {
103         assert(s);
104 
105         for (size_t i = 0; i < ELEMENTSOF(gpt_partition_type_table) - 1; i++)
106                 if (streq(s, gpt_partition_type_table[i].name)) {
107                         if (ret)
108                                 *ret = gpt_partition_type_table[i].uuid;
109                         return 0;
110                 }
111 
112         return sd_id128_from_string(s, ret);
113 }
114 
gpt_partition_type_uuid_to_arch(sd_id128_t id)115 Architecture gpt_partition_type_uuid_to_arch(sd_id128_t id) {
116         const GptPartitionType *pt;
117 
118         pt = gpt_partition_type_find_by_uuid(id);
119         if (!pt)
120                 return _ARCHITECTURE_INVALID;
121 
122         return pt->arch;
123 }
124 
gpt_partition_label_valid(const char * s)125 int gpt_partition_label_valid(const char *s) {
126         _cleanup_free_ char16_t *recoded = NULL;
127 
128         recoded = utf8_to_utf16(s, strlen(s));
129         if (!recoded)
130                 return -ENOMEM;
131 
132         return char16_strlen(recoded) <= GPT_LABEL_MAX;
133 }
134 
gpt_partition_type_from_uuid(sd_id128_t id)135 static GptPartitionType gpt_partition_type_from_uuid(sd_id128_t id) {
136         const GptPartitionType *pt;
137 
138         pt = gpt_partition_type_find_by_uuid(id);
139         if (pt)
140                 return *pt;
141 
142         return (GptPartitionType) { .uuid = id, .arch = _ARCHITECTURE_INVALID };
143 }
144 
gpt_partition_type_is_root(sd_id128_t id)145 bool gpt_partition_type_is_root(sd_id128_t id) {
146         return gpt_partition_type_from_uuid(id).is_root;
147 }
148 
gpt_partition_type_is_root_verity(sd_id128_t id)149 bool gpt_partition_type_is_root_verity(sd_id128_t id) {
150         return gpt_partition_type_from_uuid(id).is_root_verity;
151 }
152 
gpt_partition_type_is_root_verity_sig(sd_id128_t id)153 bool gpt_partition_type_is_root_verity_sig(sd_id128_t id) {
154         return gpt_partition_type_from_uuid(id).is_root_verity_sig;
155 }
156 
gpt_partition_type_is_usr(sd_id128_t id)157 bool gpt_partition_type_is_usr(sd_id128_t id) {
158         return gpt_partition_type_from_uuid(id).is_usr;
159 }
160 
gpt_partition_type_is_usr_verity(sd_id128_t id)161 bool gpt_partition_type_is_usr_verity(sd_id128_t id) {
162         return gpt_partition_type_from_uuid(id).is_usr_verity;
163 }
164 
gpt_partition_type_is_usr_verity_sig(sd_id128_t id)165 bool gpt_partition_type_is_usr_verity_sig(sd_id128_t id) {
166         return gpt_partition_type_from_uuid(id).is_usr_verity_sig;
167 }
168 
gpt_partition_type_knows_read_only(sd_id128_t id)169 bool gpt_partition_type_knows_read_only(sd_id128_t id) {
170         return gpt_partition_type_is_root(id) ||
171                 gpt_partition_type_is_usr(id) ||
172                 sd_id128_in_set(id,
173                                 GPT_HOME,
174                                 GPT_SRV,
175                                 GPT_VAR,
176                                 GPT_TMP,
177                                 GPT_XBOOTLDR) ||
178                 gpt_partition_type_is_root_verity(id) || /* pretty much implied, but let's set the bit to make things really clear */
179                 gpt_partition_type_is_usr_verity(id);    /* ditto */
180 }
181 
gpt_partition_type_knows_growfs(sd_id128_t id)182 bool gpt_partition_type_knows_growfs(sd_id128_t id) {
183         return gpt_partition_type_is_root(id) ||
184                 gpt_partition_type_is_usr(id) ||
185                 sd_id128_in_set(id,
186                                 GPT_HOME,
187                                 GPT_SRV,
188                                 GPT_VAR,
189                                 GPT_TMP,
190                                 GPT_XBOOTLDR);
191 }
192 
gpt_partition_type_knows_no_auto(sd_id128_t id)193 bool gpt_partition_type_knows_no_auto(sd_id128_t id) {
194         return gpt_partition_type_is_root(id) ||
195                 gpt_partition_type_is_root_verity(id) ||
196                 gpt_partition_type_is_usr(id) ||
197                 gpt_partition_type_is_usr_verity(id) ||
198                 sd_id128_in_set(id,
199                                 GPT_HOME,
200                                 GPT_SRV,
201                                 GPT_VAR,
202                                 GPT_TMP,
203                                 GPT_XBOOTLDR,
204                                 GPT_SWAP);
205 }
206