]> Git Repo - J-u-boot.git/blob - lib/uuid.c
acpi_table: Support platforms with unusable RSDT
[J-u-boot.git] / lib / uuid.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2011 Calxeda, Inc.
4  * Copyright 2022-2023 Arm Limited and/or its affiliates <[email protected]>
5  *
6  * Authors:
7  *   Abdellatif El Khlifi <[email protected]>
8  */
9
10 #ifndef USE_HOSTCC
11 #include <command.h>
12 #include <efi_api.h>
13 #include <env.h>
14 #include <rand.h>
15 #include <time.h>
16 #include <asm/io.h>
17 #include <part_efi.h>
18 #include <malloc.h>
19 #include <dm/uclass.h>
20 #include <rng.h>
21 #include <linux/ctype.h>
22 #include <hexdump.h>
23 #else
24 #include <stdarg.h>
25 #include <stdint.h>
26 #include <eficapsule.h>
27 #include <ctype.h>
28 #endif
29 #include <linux/types.h>
30 #include <errno.h>
31 #include <linux/kconfig.h>
32 #include <u-boot/uuid.h>
33 #include <u-boot/sha1.h>
34
35 #ifdef USE_HOSTCC
36 /* polyfill hextoul to avoid pulling in strto.c */
37 #define hextoul(cp, endp) strtoul(cp, endp, 16)
38 #endif
39
40 int uuid_str_valid(const char *uuid)
41 {
42         int i, valid;
43
44         if (uuid == NULL)
45                 return 0;
46
47         for (i = 0, valid = 1; uuid[i] && valid; i++) {
48                 switch (i) {
49                 case 8: case 13: case 18: case 23:
50                         valid = (uuid[i] == '-');
51                         break;
52                 default:
53                         valid = isxdigit(uuid[i]);
54                         break;
55                 }
56         }
57
58         if (i != UUID_STR_LEN || !valid)
59                 return 0;
60
61         return 1;
62 }
63
64 static const struct {
65         const char *string;
66         efi_guid_t guid;
67 } list_guid[] = {
68 #ifndef USE_HOSTCC
69 #ifdef CONFIG_PARTITION_TYPE_GUID
70         {"system",      PARTITION_SYSTEM_GUID},
71         {"mbr",         LEGACY_MBR_PARTITION_GUID},
72         {"msft",        PARTITION_MSFT_RESERVED_GUID},
73         {"data",        PARTITION_BASIC_DATA_GUID},
74         {"linux",       PARTITION_LINUX_FILE_SYSTEM_DATA_GUID},
75         {"raid",        PARTITION_LINUX_RAID_GUID},
76         {"swap",        PARTITION_LINUX_SWAP_GUID},
77         {"lvm",         PARTITION_LINUX_LVM_GUID},
78         {"u-boot-env",  PARTITION_U_BOOT_ENVIRONMENT},
79         {"cros-kern",   PARTITION_CROS_KERNEL},
80         {"cros-root",   PARTITION_CROS_ROOT},
81         {"cros-fw",     PARTITION_CROS_FIRMWARE},
82         {"cros-rsrv",   PARTITION_CROS_RESERVED},
83 #endif
84 #if defined(CONFIG_CMD_EFIDEBUG) || defined(CONFIG_EFI)
85         {
86                 "Device Path",
87                 EFI_DEVICE_PATH_PROTOCOL_GUID,
88         },
89         {
90                 "Device Path To Text",
91                 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID,
92         },
93         {
94                 "Device Path Utilities",
95                 EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID,
96         },
97         {
98                 "Unicode Collation 2",
99                 EFI_UNICODE_COLLATION_PROTOCOL2_GUID,
100         },
101         {
102                 "Driver Binding",
103                 EFI_DRIVER_BINDING_PROTOCOL_GUID,
104         },
105         {
106                 "Simple Text Input",
107                 EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID,
108         },
109         {
110                 "Simple Text Input Ex",
111                 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID,
112         },
113         {
114                 "Simple Text Output",
115                 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID,
116         },
117         {
118                 "Block IO",
119                 EFI_BLOCK_IO_PROTOCOL_GUID,
120         },
121         {
122                 "Simple File System",
123                 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID,
124         },
125         {
126                 "Loaded Image",
127                 EFI_LOADED_IMAGE_PROTOCOL_GUID,
128         },
129         {
130                 "Graphics Output",
131                 EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID,
132         },
133         {
134                 "HII String",
135                 EFI_HII_STRING_PROTOCOL_GUID,
136         },
137         {
138                 "HII Database",
139                 EFI_HII_DATABASE_PROTOCOL_GUID,
140         },
141         {
142                 "HII Config Routing",
143                 EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID,
144         },
145         {
146                 "Load File2",
147                 EFI_LOAD_FILE2_PROTOCOL_GUID,
148         },
149         {
150                 "Random Number Generator",
151                 EFI_RNG_PROTOCOL_GUID,
152         },
153         {
154                 "Simple Network",
155                 EFI_SIMPLE_NETWORK_PROTOCOL_GUID,
156         },
157         {
158                 "PXE Base Code",
159                 EFI_PXE_BASE_CODE_PROTOCOL_GUID,
160         },
161         {
162                 "Device-Tree Fixup",
163                 EFI_DT_FIXUP_PROTOCOL_GUID,
164         },
165         {
166                 "TCG2",
167                 EFI_TCG2_PROTOCOL_GUID,
168                 },
169         {
170                 "System Partition",
171                 PARTITION_SYSTEM_GUID
172         },
173         {
174                 "Firmware Management",
175                 EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID
176         },
177         /* Configuration table GUIDs */
178         {
179                 "ACPI table",
180                 EFI_ACPI_TABLE_GUID,
181         },
182         {
183                 "EFI System Resource Table",
184                 EFI_SYSTEM_RESOURCE_TABLE_GUID,
185         },
186         {
187                 "device tree",
188                 EFI_FDT_GUID,
189         },
190         {
191                 "SMBIOS table",
192                 SMBIOS_TABLE_GUID,
193         },
194         {
195                 "SMBIOS3 table",
196                 SMBIOS3_TABLE_GUID,
197         },
198         {
199                 "Runtime properties",
200                 EFI_RT_PROPERTIES_TABLE_GUID,
201         },
202         {
203                 "TCG2 Final Events Table",
204                 EFI_TCG2_FINAL_EVENTS_TABLE_GUID,
205         },
206         {
207                 "EFI Conformance Profiles Table",
208                 EFI_CONFORMANCE_PROFILES_TABLE_GUID,
209         },
210 #ifdef CONFIG_EFI_RISCV_BOOT_PROTOCOL
211         {
212                 "RISC-V Boot",
213                 RISCV_EFI_BOOT_PROTOCOL_GUID,
214         },
215 #endif
216 #endif /* CONFIG_CMD_EFIDEBUG */
217 #ifdef CONFIG_CMD_NVEDIT_EFI
218         /* signature database */
219         {
220                 "EFI_GLOBAL_VARIABLE_GUID",
221                 EFI_GLOBAL_VARIABLE_GUID,
222         },
223         {
224                 "EFI_IMAGE_SECURITY_DATABASE_GUID",
225                 EFI_IMAGE_SECURITY_DATABASE_GUID,
226         },
227         /* certificate types */
228         {
229                 "EFI_CERT_SHA256_GUID",
230                 EFI_CERT_SHA256_GUID,
231         },
232         {
233                 "EFI_CERT_X509_GUID",
234                 EFI_CERT_X509_GUID,
235         },
236         {
237                 "EFI_CERT_TYPE_PKCS7_GUID",
238                 EFI_CERT_TYPE_PKCS7_GUID,
239         },
240 #endif
241 #if defined(CONFIG_CMD_EFIDEBUG) || defined(CONFIG_EFI)
242         { "EFI_LZMA_COMPRESSED", EFI_LZMA_COMPRESSED },
243         { "EFI_DXE_SERVICES", EFI_DXE_SERVICES },
244         { "EFI_HOB_LIST", EFI_HOB_LIST },
245         { "EFI_MEMORY_TYPE", EFI_MEMORY_TYPE },
246         { "EFI_MEM_STATUS_CODE_REC", EFI_MEM_STATUS_CODE_REC },
247         { "EFI_GUID_EFI_ACPI1", EFI_GUID_EFI_ACPI1 },
248 #endif
249 #endif /* !USE_HOSTCC */
250 };
251
252 int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin)
253 {
254         int i;
255
256         for (i = 0; i < ARRAY_SIZE(list_guid); i++) {
257                 if (!strcmp(list_guid[i].string, guid_str)) {
258                         memcpy(guid_bin, &list_guid[i].guid, 16);
259                         return 0;
260                 }
261         }
262         return -ENODEV;
263 }
264
265 const char *uuid_guid_get_str(const unsigned char *guid_bin)
266 {
267         int i;
268
269         for (i = 0; i < ARRAY_SIZE(list_guid); i++) {
270                 if (!memcmp(list_guid[i].guid.b, guid_bin, 16)) {
271                         return list_guid[i].string;
272                 }
273         }
274         return NULL;
275 }
276
277 int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
278                     int str_format)
279 {
280         uint16_t tmp16;
281         uint32_t tmp32;
282         uint64_t tmp64;
283
284         if (!uuid_str_valid(uuid_str)) {
285 #ifdef CONFIG_PARTITION_TYPE_GUID
286                 if (!uuid_guid_get_bin(uuid_str, uuid_bin))
287                         return 0;
288 #endif
289                 return -EINVAL;
290         }
291
292         if (str_format == UUID_STR_FORMAT_STD) {
293                 tmp32 = cpu_to_be32(hextoul(uuid_str, NULL));
294                 memcpy(uuid_bin, &tmp32, 4);
295
296                 tmp16 = cpu_to_be16(hextoul(uuid_str + 9, NULL));
297                 memcpy(uuid_bin + 4, &tmp16, 2);
298
299                 tmp16 = cpu_to_be16(hextoul(uuid_str + 14, NULL));
300                 memcpy(uuid_bin + 6, &tmp16, 2);
301         } else {
302                 tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
303                 memcpy(uuid_bin, &tmp32, 4);
304
305                 tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
306                 memcpy(uuid_bin + 4, &tmp16, 2);
307
308                 tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
309                 memcpy(uuid_bin + 6, &tmp16, 2);
310         }
311
312         tmp16 = cpu_to_be16(hextoul(uuid_str + 19, NULL));
313         memcpy(uuid_bin + 8, &tmp16, 2);
314
315         tmp64 = cpu_to_be64(hextoul(uuid_str + 24, NULL));
316         memcpy(uuid_bin + 10, (char *)&tmp64 + 2, 6);
317
318         return 0;
319 }
320
321 int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
322 {
323         uint16_t tmp16;
324         uint32_t tmp32;
325         uint64_t tmp64;
326
327         if (!uuid_str_valid(uuid_str) || !uuid_bin)
328                 return -EINVAL;
329
330         tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
331         memcpy(uuid_bin, &tmp32, 4);
332
333         tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
334         memcpy(uuid_bin + 4, &tmp16, 2);
335
336         tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
337         memcpy(uuid_bin + 6, &tmp16, 2);
338
339         tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
340         memcpy(uuid_bin + 8, &tmp16, 2);
341
342         tmp64 = cpu_to_le64(hextoul(uuid_str + 24, NULL));
343         memcpy(uuid_bin + 10, &tmp64, 6);
344
345         return 0;
346 }
347
348 void uuid_bin_to_str(const unsigned char *uuid_bin, char *uuid_str,
349                      int str_format)
350 {
351         const uint8_t uuid_char_order[UUID_BIN_LEN] = {0, 1, 2, 3, 4, 5, 6, 7, 8,
352                                                   9, 10, 11, 12, 13, 14, 15};
353         const uint8_t guid_char_order[UUID_BIN_LEN] = {3, 2, 1, 0, 5, 4, 7, 6, 8,
354                                                   9, 10, 11, 12, 13, 14, 15};
355         const uint8_t *char_order;
356         const char *format;
357         int i;
358
359         /*
360          * UUID and GUID bin data - always in big endian:
361          * 4B-2B-2B-2B-6B
362          * be be be be be
363          */
364         if (str_format & UUID_STR_FORMAT_GUID)
365                 char_order = guid_char_order;
366         else
367                 char_order = uuid_char_order;
368         if (str_format & UUID_STR_UPPER_CASE)
369                 format = "%02X";
370         else
371                 format = "%02x";
372
373         for (i = 0; i < 16; i++) {
374                 sprintf(uuid_str, format, uuid_bin[char_order[i]]);
375                 uuid_str += 2;
376                 switch (i) {
377                 case 3:
378                 case 5:
379                 case 7:
380                 case 9:
381                         *uuid_str++ = '-';
382                         break;
383                 }
384         }
385 }
386
387 static void configure_uuid(struct uuid *uuid, unsigned char version)
388 {
389         uint16_t tmp;
390
391         /* Configure variant/version bits */
392         tmp = be16_to_cpu(uuid->time_hi_and_version);
393         tmp = (tmp & ~UUID_VERSION_MASK) | (version << UUID_VERSION_SHIFT);
394         uuid->time_hi_and_version = cpu_to_be16(tmp);
395
396         uuid->clock_seq_hi_and_reserved &= ~UUID_VARIANT_MASK;
397         uuid->clock_seq_hi_and_reserved |= (UUID_VARIANT << UUID_VARIANT_SHIFT);
398 }
399
400 void gen_v5_guid(const struct uuid *namespace, struct efi_guid *guid, ...)
401 {
402         sha1_context ctx;
403         va_list args;
404         const uint8_t *data;
405         uint32_t *tmp32;
406         uint16_t *tmp16;
407         uint8_t hash[SHA1_SUM_LEN];
408
409         sha1_starts(&ctx);
410         /* Hash the namespace UUID as salt */
411         sha1_update(&ctx, (unsigned char *)namespace, UUID_BIN_LEN);
412         va_start(args, guid);
413
414         while ((data = va_arg(args, const uint8_t *))) {
415                 unsigned int len = va_arg(args, size_t);
416
417                 sha1_update(&ctx, data, len);
418         }
419
420         va_end(args);
421         sha1_finish(&ctx, hash);
422
423         /* Truncate the hash into output UUID, it is already big endian */
424         memcpy(guid, hash, sizeof(*guid));
425
426         configure_uuid((struct uuid *)guid, 5);
427
428         /* Make little endian */
429         tmp32 = (uint32_t *)&guid->b[0];
430         *tmp32 = cpu_to_le32(be32_to_cpu(*tmp32));
431         tmp16 = (uint16_t *)&guid->b[4];
432         *tmp16 = cpu_to_le16(be16_to_cpu(*tmp16));
433         tmp16 = (uint16_t *)&guid->b[6];
434         *tmp16 = cpu_to_le16(be16_to_cpu(*tmp16));
435 }
436
437 #ifndef USE_HOSTCC
438 #if defined(CONFIG_RANDOM_UUID) || defined(CONFIG_CMD_UUID)
439 void gen_rand_uuid(unsigned char *uuid_bin)
440 {
441         u32 ptr[4];
442         struct uuid *uuid = (struct uuid *)ptr;
443         int i, ret;
444         struct udevice *devp;
445         u32 randv = 0;
446
447         if (CONFIG_IS_ENABLED(DM_RNG)) {
448                 ret = uclass_get_device(UCLASS_RNG, 0, &devp);
449                 if (!ret) {
450                         ret = dm_rng_read(devp, &randv, sizeof(randv));
451                         if (ret < 0)
452                                 randv = 0;
453                 }
454         }
455         if (randv)
456                 srand(randv);
457         else
458                 srand(get_ticks() + rand());
459
460         /* Set all fields randomly */
461         for (i = 0; i < 4; i++)
462                 ptr[i] = rand();
463
464         configure_uuid(uuid, UUID_VERSION);
465
466         memcpy(uuid_bin, uuid, 16);
467 }
468
469 void gen_rand_uuid_str(char *uuid_str, int str_format)
470 {
471         unsigned char uuid_bin[UUID_BIN_LEN];
472
473         /* Generate UUID (big endian) */
474         gen_rand_uuid(uuid_bin);
475
476         /* Convert UUID bin to UUID or GUID formated STRING  */
477         uuid_bin_to_str(uuid_bin, uuid_str, str_format);
478 }
479
480 #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CMD_UUID)
481 int do_uuid(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
482 {
483         char uuid[UUID_STR_LEN + 1];
484         int str_format;
485
486         if (!strcmp(argv[0], "uuid"))
487                 str_format = UUID_STR_FORMAT_STD;
488         else
489                 str_format = UUID_STR_FORMAT_GUID;
490
491         if (argc > 2)
492                 return CMD_RET_USAGE;
493
494         gen_rand_uuid_str(uuid, str_format);
495
496         if (argc == 1)
497                 printf("%s\n", uuid);
498         else
499                 env_set(argv[1], uuid);
500
501         return CMD_RET_SUCCESS;
502 }
503
504 U_BOOT_CMD(uuid, CONFIG_SYS_MAXARGS, 1, do_uuid,
505            "UUID - generate random Universally Unique Identifier",
506            "[<varname>]\n"
507            "Argument:\n"
508            "varname: for set result in a environment variable\n"
509            "e.g. uuid uuid_env"
510 );
511
512 U_BOOT_CMD(guid, CONFIG_SYS_MAXARGS, 1, do_uuid,
513            "GUID - generate Globally Unique Identifier based on random UUID",
514            "[<varname>]\n"
515            "Argument:\n"
516            "varname: for set result in a environment variable\n"
517            "e.g. guid guid_env"
518 );
519 #endif /* CONFIG_CMD_UUID */
520 #endif /* CONFIG_RANDOM_UUID || CONFIG_CMD_UUID */
521 #endif /* !USE_HOSTCC */
This page took 0.061654 seconds and 4 git commands to generate.