]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
e11938ea JH |
2 | /* |
3 | * Copyright 2011 Calxeda, Inc. | |
7048f26c AEK |
4 | * Copyright 2022-2023 Arm Limited and/or its affiliates <[email protected]> |
5 | * | |
6 | * Authors: | |
7 | * Abdellatif El Khlifi <[email protected]> | |
e11938ea JH |
8 | */ |
9 | ||
966b16c5 SG |
10 | #define LOG_CATEGOT LOGC_CORE |
11 | ||
09140113 | 12 | #include <command.h> |
3adae642 | 13 | #include <efi_api.h> |
9fb625ce | 14 | #include <env.h> |
90526e9f | 15 | #include <rand.h> |
1045315d | 16 | #include <time.h> |
ba06b3c5 | 17 | #include <uuid.h> |
e11938ea | 18 | #include <linux/ctype.h> |
a96a0e61 | 19 | #include <errno.h> |
d718ded0 PM |
20 | #include <asm/io.h> |
21 | #include <part_efi.h> | |
22 | #include <malloc.h> | |
92fdad28 MB |
23 | #include <dm/uclass.h> |
24 | #include <rng.h> | |
e11938ea | 25 | |
e11938ea JH |
26 | int uuid_str_valid(const char *uuid) |
27 | { | |
28 | int i, valid; | |
29 | ||
30 | if (uuid == NULL) | |
31 | return 0; | |
32 | ||
33 | for (i = 0, valid = 1; uuid[i] && valid; i++) { | |
34 | switch (i) { | |
35 | case 8: case 13: case 18: case 23: | |
36 | valid = (uuid[i] == '-'); | |
37 | break; | |
38 | default: | |
39 | valid = isxdigit(uuid[i]); | |
40 | break; | |
41 | } | |
42 | } | |
43 | ||
d718ded0 | 44 | if (i != UUID_STR_LEN || !valid) |
e11938ea JH |
45 | return 0; |
46 | ||
47 | return 1; | |
48 | } | |
49 | ||
bcb41dca PD |
50 | static const struct { |
51 | const char *string; | |
52 | efi_guid_t guid; | |
53 | } list_guid[] = { | |
c1528f32 | 54 | #ifdef CONFIG_PARTITION_TYPE_GUID |
bcb41dca PD |
55 | {"system", PARTITION_SYSTEM_GUID}, |
56 | {"mbr", LEGACY_MBR_PARTITION_GUID}, | |
57 | {"msft", PARTITION_MSFT_RESERVED_GUID}, | |
58 | {"data", PARTITION_BASIC_DATA_GUID}, | |
59 | {"linux", PARTITION_LINUX_FILE_SYSTEM_DATA_GUID}, | |
60 | {"raid", PARTITION_LINUX_RAID_GUID}, | |
61 | {"swap", PARTITION_LINUX_SWAP_GUID}, | |
c0364ce1 RV |
62 | {"lvm", PARTITION_LINUX_LVM_GUID}, |
63 | {"u-boot-env", PARTITION_U_BOOT_ENVIRONMENT}, | |
966b16c5 SG |
64 | {"cros-kern", PARTITION_CROS_KERNEL}, |
65 | {"cros-root", PARTITION_CROS_ROOT}, | |
66 | {"cros-fw", PARTITION_CROS_FIRMWARE}, | |
67 | {"cros-rsrv", PARTITION_CROS_RESERVED}, | |
c1528f32 | 68 | #endif |
4e5e49a3 | 69 | #if defined(CONFIG_CMD_EFIDEBUG) || defined(CONFIG_EFI) |
3adae642 HS |
70 | { |
71 | "Device Path", | |
72 | EFI_DEVICE_PATH_PROTOCOL_GUID, | |
73 | }, | |
74 | { | |
75 | "Device Path To Text", | |
76 | EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID, | |
77 | }, | |
78 | { | |
79 | "Device Path Utilities", | |
80 | EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID, | |
81 | }, | |
82 | { | |
83 | "Unicode Collation 2", | |
84 | EFI_UNICODE_COLLATION_PROTOCOL2_GUID, | |
85 | }, | |
86 | { | |
87 | "Driver Binding", | |
88 | EFI_DRIVER_BINDING_PROTOCOL_GUID, | |
89 | }, | |
90 | { | |
91 | "Simple Text Input", | |
92 | EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID, | |
93 | }, | |
94 | { | |
95 | "Simple Text Input Ex", | |
96 | EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID, | |
97 | }, | |
98 | { | |
99 | "Simple Text Output", | |
100 | EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID, | |
101 | }, | |
102 | { | |
103 | "Block IO", | |
104 | EFI_BLOCK_IO_PROTOCOL_GUID, | |
105 | }, | |
106 | { | |
107 | "Simple File System", | |
108 | EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, | |
109 | }, | |
110 | { | |
111 | "Loaded Image", | |
112 | EFI_LOADED_IMAGE_PROTOCOL_GUID, | |
113 | }, | |
114 | { | |
115 | "Graphics Output", | |
116 | EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, | |
117 | }, | |
118 | { | |
119 | "HII String", | |
120 | EFI_HII_STRING_PROTOCOL_GUID, | |
121 | }, | |
122 | { | |
123 | "HII Database", | |
124 | EFI_HII_DATABASE_PROTOCOL_GUID, | |
125 | }, | |
126 | { | |
127 | "HII Config Routing", | |
128 | EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID, | |
129 | }, | |
130 | { | |
131 | "Load File2", | |
132 | EFI_LOAD_FILE2_PROTOCOL_GUID, | |
133 | }, | |
134 | { | |
135 | "Random Number Generator", | |
136 | EFI_RNG_PROTOCOL_GUID, | |
137 | }, | |
138 | { | |
139 | "Simple Network", | |
140 | EFI_SIMPLE_NETWORK_PROTOCOL_GUID, | |
141 | }, | |
142 | { | |
143 | "PXE Base Code", | |
144 | EFI_PXE_BASE_CODE_PROTOCOL_GUID, | |
145 | }, | |
146 | { | |
147 | "Device-Tree Fixup", | |
148 | EFI_DT_FIXUP_PROTOCOL_GUID, | |
149 | }, | |
38040a63 HS |
150 | { |
151 | "TCG2", | |
152 | EFI_TCG2_PROTOCOL_GUID, | |
153 | }, | |
3adae642 HS |
154 | { |
155 | "System Partition", | |
156 | PARTITION_SYSTEM_GUID | |
157 | }, | |
158 | { | |
159 | "Firmware Management", | |
160 | EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID | |
161 | }, | |
162 | /* Configuration table GUIDs */ | |
163 | { | |
164 | "ACPI table", | |
165 | EFI_ACPI_TABLE_GUID, | |
166 | }, | |
167 | { | |
168 | "EFI System Resource Table", | |
169 | EFI_SYSTEM_RESOURCE_TABLE_GUID, | |
170 | }, | |
171 | { | |
172 | "device tree", | |
173 | EFI_FDT_GUID, | |
174 | }, | |
175 | { | |
176 | "SMBIOS table", | |
177 | SMBIOS_TABLE_GUID, | |
178 | }, | |
91cc06bc HS |
179 | { |
180 | "SMBIOS3 table", | |
181 | SMBIOS3_TABLE_GUID, | |
182 | }, | |
3adae642 HS |
183 | { |
184 | "Runtime properties", | |
185 | EFI_RT_PROPERTIES_TABLE_GUID, | |
186 | }, | |
187 | { | |
188 | "TCG2 Final Events Table", | |
189 | EFI_TCG2_FINAL_EVENTS_TABLE_GUID, | |
190 | }, | |
6b92c173 JM |
191 | { |
192 | "EFI Conformance Profiles Table", | |
193 | EFI_CONFORMANCE_PROFILES_TABLE_GUID, | |
194 | }, | |
8d4c4265 HS |
195 | #ifdef CONFIG_EFI_RISCV_BOOT_PROTOCOL |
196 | { | |
197 | "RISC-V Boot", | |
198 | RISCV_EFI_BOOT_PROTOCOL_GUID, | |
199 | }, | |
3adae642 | 200 | #endif |
8d4c4265 | 201 | #endif /* CONFIG_CMD_EFIDEBUG */ |
983a5a2e HS |
202 | #ifdef CONFIG_CMD_NVEDIT_EFI |
203 | /* signature database */ | |
204 | { | |
205 | "EFI_GLOBAL_VARIABLE_GUID", | |
206 | EFI_GLOBAL_VARIABLE_GUID, | |
207 | }, | |
208 | { | |
209 | "EFI_IMAGE_SECURITY_DATABASE_GUID", | |
210 | EFI_IMAGE_SECURITY_DATABASE_GUID, | |
211 | }, | |
212 | /* certificate types */ | |
213 | { | |
214 | "EFI_CERT_SHA256_GUID", | |
215 | EFI_CERT_SHA256_GUID, | |
216 | }, | |
217 | { | |
218 | "EFI_CERT_X509_GUID", | |
219 | EFI_CERT_X509_GUID, | |
220 | }, | |
221 | { | |
222 | "EFI_CERT_TYPE_PKCS7_GUID", | |
223 | EFI_CERT_TYPE_PKCS7_GUID, | |
224 | }, | |
225 | #endif | |
3710802e | 226 | #if defined(CONFIG_CMD_EFIDEBUG) || defined(CONFIG_EFI) |
ac93275d SG |
227 | { "EFI_LZMA_COMPRESSED", EFI_LZMA_COMPRESSED }, |
228 | { "EFI_DXE_SERVICES", EFI_DXE_SERVICES }, | |
229 | { "EFI_HOB_LIST", EFI_HOB_LIST }, | |
230 | { "EFI_MEMORY_TYPE", EFI_MEMORY_TYPE }, | |
231 | { "EFI_MEM_STATUS_CODE_REC", EFI_MEM_STATUS_CODE_REC }, | |
232 | { "EFI_GUID_EFI_ACPI1", EFI_GUID_EFI_ACPI1 }, | |
233 | #endif | |
bcb41dca PD |
234 | }; |
235 | ||
bcb41dca PD |
236 | int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin) |
237 | { | |
238 | int i; | |
239 | ||
240 | for (i = 0; i < ARRAY_SIZE(list_guid); i++) { | |
241 | if (!strcmp(list_guid[i].string, guid_str)) { | |
242 | memcpy(guid_bin, &list_guid[i].guid, 16); | |
243 | return 0; | |
244 | } | |
245 | } | |
246 | return -ENODEV; | |
247 | } | |
248 | ||
31ce367c | 249 | const char *uuid_guid_get_str(const unsigned char *guid_bin) |
bcb41dca PD |
250 | { |
251 | int i; | |
252 | ||
bcb41dca PD |
253 | for (i = 0; i < ARRAY_SIZE(list_guid); i++) { |
254 | if (!memcmp(list_guid[i].guid.b, guid_bin, 16)) { | |
31ce367c | 255 | return list_guid[i].string; |
bcb41dca PD |
256 | } |
257 | } | |
31ce367c | 258 | return NULL; |
bcb41dca | 259 | } |
bcb41dca | 260 | |
2c2ca207 SG |
261 | int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin, |
262 | int str_format) | |
e11938ea JH |
263 | { |
264 | uint16_t tmp16; | |
265 | uint32_t tmp32; | |
266 | uint64_t tmp64; | |
267 | ||
bcb41dca | 268 | if (!uuid_str_valid(uuid_str)) { |
966b16c5 | 269 | log_debug("not valid\n"); |
bcb41dca PD |
270 | #ifdef CONFIG_PARTITION_TYPE_GUID |
271 | if (!uuid_guid_get_bin(uuid_str, uuid_bin)) | |
272 | return 0; | |
273 | #endif | |
a96a0e61 | 274 | return -EINVAL; |
bcb41dca | 275 | } |
a96a0e61 | 276 | |
d718ded0 | 277 | if (str_format == UUID_STR_FORMAT_STD) { |
7e5f460e | 278 | tmp32 = cpu_to_be32(hextoul(uuid_str, NULL)); |
d718ded0 | 279 | memcpy(uuid_bin, &tmp32, 4); |
e11938ea | 280 | |
7e5f460e | 281 | tmp16 = cpu_to_be16(hextoul(uuid_str + 9, NULL)); |
d718ded0 | 282 | memcpy(uuid_bin + 4, &tmp16, 2); |
e11938ea | 283 | |
7e5f460e | 284 | tmp16 = cpu_to_be16(hextoul(uuid_str + 14, NULL)); |
d718ded0 PM |
285 | memcpy(uuid_bin + 6, &tmp16, 2); |
286 | } else { | |
7e5f460e | 287 | tmp32 = cpu_to_le32(hextoul(uuid_str, NULL)); |
d718ded0 | 288 | memcpy(uuid_bin, &tmp32, 4); |
e11938ea | 289 | |
7e5f460e | 290 | tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL)); |
d718ded0 | 291 | memcpy(uuid_bin + 4, &tmp16, 2); |
e11938ea | 292 | |
7e5f460e | 293 | tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL)); |
d718ded0 PM |
294 | memcpy(uuid_bin + 6, &tmp16, 2); |
295 | } | |
296 | ||
7e5f460e | 297 | tmp16 = cpu_to_be16(hextoul(uuid_str + 19, NULL)); |
d718ded0 | 298 | memcpy(uuid_bin + 8, &tmp16, 2); |
e11938ea | 299 | |
d718ded0 PM |
300 | tmp64 = cpu_to_be64(simple_strtoull(uuid_str + 24, NULL, 16)); |
301 | memcpy(uuid_bin + 10, (char *)&tmp64 + 2, 6); | |
a96a0e61 PM |
302 | |
303 | return 0; | |
304 | } | |
305 | ||
7048f26c AEK |
306 | int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin) |
307 | { | |
308 | u16 tmp16; | |
309 | u32 tmp32; | |
310 | u64 tmp64; | |
311 | ||
312 | if (!uuid_str_valid(uuid_str) || !uuid_bin) | |
313 | return -EINVAL; | |
314 | ||
315 | tmp32 = cpu_to_le32(hextoul(uuid_str, NULL)); | |
316 | memcpy(uuid_bin, &tmp32, 4); | |
317 | ||
318 | tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL)); | |
319 | memcpy(uuid_bin + 4, &tmp16, 2); | |
320 | ||
321 | tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL)); | |
322 | memcpy(uuid_bin + 6, &tmp16, 2); | |
323 | ||
324 | tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL)); | |
325 | memcpy(uuid_bin + 8, &tmp16, 2); | |
326 | ||
327 | tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16)); | |
328 | memcpy(uuid_bin + 10, &tmp64, 6); | |
329 | ||
330 | return 0; | |
331 | } | |
332 | ||
2c2ca207 SG |
333 | void uuid_bin_to_str(const unsigned char *uuid_bin, char *uuid_str, |
334 | int str_format) | |
a96a0e61 | 335 | { |
d718ded0 PM |
336 | const u8 uuid_char_order[UUID_BIN_LEN] = {0, 1, 2, 3, 4, 5, 6, 7, 8, |
337 | 9, 10, 11, 12, 13, 14, 15}; | |
338 | const u8 guid_char_order[UUID_BIN_LEN] = {3, 2, 1, 0, 5, 4, 7, 6, 8, | |
339 | 9, 10, 11, 12, 13, 14, 15}; | |
340 | const u8 *char_order; | |
3bad256f | 341 | const char *format; |
a96a0e61 PM |
342 | int i; |
343 | ||
d718ded0 PM |
344 | /* |
345 | * UUID and GUID bin data - always in big endian: | |
346 | * 4B-2B-2B-2B-6B | |
347 | * be be be be be | |
348 | */ | |
3bad256f HS |
349 | if (str_format & UUID_STR_FORMAT_GUID) |
350 | char_order = guid_char_order; | |
351 | else | |
d718ded0 | 352 | char_order = uuid_char_order; |
3bad256f HS |
353 | if (str_format & UUID_STR_UPPER_CASE) |
354 | format = "%02X"; | |
d718ded0 | 355 | else |
3bad256f | 356 | format = "%02x"; |
d718ded0 | 357 | |
a96a0e61 | 358 | for (i = 0; i < 16; i++) { |
3bad256f | 359 | sprintf(uuid_str, format, uuid_bin[char_order[i]]); |
d718ded0 | 360 | uuid_str += 2; |
a96a0e61 PM |
361 | switch (i) { |
362 | case 3: | |
363 | case 5: | |
364 | case 7: | |
365 | case 9: | |
d718ded0 | 366 | *uuid_str++ = '-'; |
a96a0e61 PM |
367 | break; |
368 | } | |
369 | } | |
e11938ea | 370 | } |
4e4815fe | 371 | |
89c8230d | 372 | #if defined(CONFIG_RANDOM_UUID) || defined(CONFIG_CMD_UUID) |
4e4815fe PM |
373 | void gen_rand_uuid(unsigned char *uuid_bin) |
374 | { | |
a1b633df HS |
375 | u32 ptr[4]; |
376 | struct uuid *uuid = (struct uuid *)ptr; | |
92fdad28 MB |
377 | int i, ret; |
378 | struct udevice *devp; | |
379 | u32 randv = 0; | |
380 | ||
381 | if (IS_ENABLED(CONFIG_DM_RNG)) { | |
382 | ret = uclass_get_device(UCLASS_RNG, 0, &devp); | |
70a9f4d2 | 383 | if (!ret) { |
92fdad28 MB |
384 | ret = dm_rng_read(devp, &randv, sizeof(randv)); |
385 | if (ret < 0) | |
386 | randv = 0; | |
387 | } | |
388 | } | |
389 | if (randv) | |
390 | srand(randv); | |
391 | else | |
392 | srand(get_ticks() + rand()); | |
4ccf678f | 393 | |
4e4815fe | 394 | /* Set all fields randomly */ |
a1b633df HS |
395 | for (i = 0; i < 4; i++) |
396 | ptr[i] = rand(); | |
4e4815fe | 397 | |
a1b633df | 398 | clrsetbits_be16(&uuid->time_hi_and_version, |
4e4815fe PM |
399 | UUID_VERSION_MASK, |
400 | UUID_VERSION << UUID_VERSION_SHIFT); | |
401 | ||
a1b633df | 402 | clrsetbits_8(&uuid->clock_seq_hi_and_reserved, |
4e4815fe PM |
403 | UUID_VARIANT_MASK, |
404 | UUID_VARIANT << UUID_VARIANT_SHIFT); | |
405 | ||
a1b633df | 406 | memcpy(uuid_bin, uuid, 16); |
4e4815fe PM |
407 | } |
408 | ||
4e4815fe PM |
409 | void gen_rand_uuid_str(char *uuid_str, int str_format) |
410 | { | |
411 | unsigned char uuid_bin[UUID_BIN_LEN]; | |
412 | ||
413 | /* Generate UUID (big endian) */ | |
414 | gen_rand_uuid(uuid_bin); | |
415 | ||
416 | /* Convert UUID bin to UUID or GUID formated STRING */ | |
417 | uuid_bin_to_str(uuid_bin, uuid_str, str_format); | |
418 | } | |
89c8230d | 419 | |
05f6da3f | 420 | #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CMD_UUID) |
09140113 | 421 | int do_uuid(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) |
89c8230d PM |
422 | { |
423 | char uuid[UUID_STR_LEN + 1]; | |
424 | int str_format; | |
425 | ||
426 | if (!strcmp(argv[0], "uuid")) | |
427 | str_format = UUID_STR_FORMAT_STD; | |
428 | else | |
429 | str_format = UUID_STR_FORMAT_GUID; | |
430 | ||
431 | if (argc > 2) | |
432 | return CMD_RET_USAGE; | |
433 | ||
434 | gen_rand_uuid_str(uuid, str_format); | |
435 | ||
436 | if (argc == 1) | |
437 | printf("%s\n", uuid); | |
438 | else | |
382bee57 | 439 | env_set(argv[1], uuid); |
89c8230d PM |
440 | |
441 | return CMD_RET_SUCCESS; | |
442 | } | |
443 | ||
444 | U_BOOT_CMD(uuid, CONFIG_SYS_MAXARGS, 1, do_uuid, | |
445 | "UUID - generate random Universally Unique Identifier", | |
446 | "[<varname>]\n" | |
447 | "Argument:\n" | |
448 | "varname: for set result in a environment variable\n" | |
449 | "e.g. uuid uuid_env" | |
450 | ); | |
451 | ||
452 | U_BOOT_CMD(guid, CONFIG_SYS_MAXARGS, 1, do_uuid, | |
453 | "GUID - generate Globally Unique Identifier based on random UUID", | |
454 | "[<varname>]\n" | |
455 | "Argument:\n" | |
456 | "varname: for set result in a environment variable\n" | |
457 | "e.g. guid guid_env" | |
458 | ); | |
39206382 PM |
459 | #endif /* CONFIG_CMD_UUID */ |
460 | #endif /* CONFIG_RANDOM_UUID || CONFIG_CMD_UUID */ |