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