xref: /rk3399_rockchip-uboot/lib/uuid.c (revision a96a0e6153e3d9071c1a4516bf3e94c4cd96c77c)
1e11938eaSJason Hobbs /*
2e11938eaSJason Hobbs  * Copyright 2011 Calxeda, Inc.
3e11938eaSJason Hobbs  *
41a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
5e11938eaSJason Hobbs  */
6e11938eaSJason Hobbs 
7e11938eaSJason Hobbs #include <linux/ctype.h>
8*a96a0e61SPrzemyslaw Marczak #include <errno.h>
9*a96a0e61SPrzemyslaw Marczak #include <common.h>
10*a96a0e61SPrzemyslaw Marczak 
11*a96a0e61SPrzemyslaw Marczak #define UUID_STR_LEN		36
12e11938eaSJason Hobbs 
13e11938eaSJason Hobbs /*
14*a96a0e61SPrzemyslaw Marczak  * UUID - Universally Unique IDentifier - 128 bits unique number.
15*a96a0e61SPrzemyslaw Marczak  *        There are 5 versions and one variant of UUID defined by RFC4122
16*a96a0e61SPrzemyslaw Marczak  *        specification. Depends on version uuid number base on a time,
17*a96a0e61SPrzemyslaw Marczak  *        host name, MAC address or random data.
18e11938eaSJason Hobbs  *
19*a96a0e61SPrzemyslaw Marczak  * UUID binary format (16 bytes):
20*a96a0e61SPrzemyslaw Marczak  *
21*a96a0e61SPrzemyslaw Marczak  * 4B-2B-2B-2B-6B (big endian - network byte order)
22*a96a0e61SPrzemyslaw Marczak  *
23*a96a0e61SPrzemyslaw Marczak  * UUID string is 36 length of characters (36 bytes):
24e11938eaSJason Hobbs  *
25e11938eaSJason Hobbs  * 0        9    14   19   24
26e11938eaSJason Hobbs  * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
27*a96a0e61SPrzemyslaw Marczak  *    be     be   be   be       be
28*a96a0e61SPrzemyslaw Marczak  *
29*a96a0e61SPrzemyslaw Marczak  * where x is a hexadecimal character. Fields are separated by '-'s.
30*a96a0e61SPrzemyslaw Marczak  * When converting to a binary UUID, le means the field should be converted
31*a96a0e61SPrzemyslaw Marczak  * to little endian and be means it should be converted to big endian.
32*a96a0e61SPrzemyslaw Marczak  *
33*a96a0e61SPrzemyslaw Marczak  * UUID is also used as GUID (Globally Unique Identifier) with the same binary
34*a96a0e61SPrzemyslaw Marczak  * format but it differs in string format like below.
35*a96a0e61SPrzemyslaw Marczak  *
36*a96a0e61SPrzemyslaw Marczak  * GUID:
37*a96a0e61SPrzemyslaw Marczak  * 0        9    14   19   24
38*a96a0e61SPrzemyslaw Marczak  * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
39e11938eaSJason Hobbs  *    le     le   le   be       be
40*a96a0e61SPrzemyslaw Marczak  *
41*a96a0e61SPrzemyslaw Marczak  * GUID is used e.g. in GPT (GUID Partition Table) as a partiions unique id.
42e11938eaSJason Hobbs  */
43e11938eaSJason Hobbs 
44e11938eaSJason Hobbs int uuid_str_valid(const char *uuid)
45e11938eaSJason Hobbs {
46e11938eaSJason Hobbs 	int i, valid;
47e11938eaSJason Hobbs 
48e11938eaSJason Hobbs 	if (uuid == NULL)
49e11938eaSJason Hobbs 		return 0;
50e11938eaSJason Hobbs 
51e11938eaSJason Hobbs 	for (i = 0, valid = 1; uuid[i] && valid; i++) {
52e11938eaSJason Hobbs 		switch (i) {
53e11938eaSJason Hobbs 		case 8: case 13: case 18: case 23:
54e11938eaSJason Hobbs 			valid = (uuid[i] == '-');
55e11938eaSJason Hobbs 			break;
56e11938eaSJason Hobbs 		default:
57e11938eaSJason Hobbs 			valid = isxdigit(uuid[i]);
58e11938eaSJason Hobbs 			break;
59e11938eaSJason Hobbs 		}
60e11938eaSJason Hobbs 	}
61e11938eaSJason Hobbs 
62e11938eaSJason Hobbs 	if (i != 36 || !valid)
63e11938eaSJason Hobbs 		return 0;
64e11938eaSJason Hobbs 
65e11938eaSJason Hobbs 	return 1;
66e11938eaSJason Hobbs }
67e11938eaSJason Hobbs 
68*a96a0e61SPrzemyslaw Marczak int uuid_str_to_bin(char *uuid, unsigned char *out)
69e11938eaSJason Hobbs {
70e11938eaSJason Hobbs 	uint16_t tmp16;
71e11938eaSJason Hobbs 	uint32_t tmp32;
72e11938eaSJason Hobbs 	uint64_t tmp64;
73e11938eaSJason Hobbs 
74e11938eaSJason Hobbs 	if (!uuid || !out)
75*a96a0e61SPrzemyslaw Marczak 		return -EINVAL;
76*a96a0e61SPrzemyslaw Marczak 
77*a96a0e61SPrzemyslaw Marczak 	if (strlen(uuid) != UUID_STR_LEN)
78*a96a0e61SPrzemyslaw Marczak 		return -EINVAL;
79e11938eaSJason Hobbs 
80e11938eaSJason Hobbs 	tmp32 = cpu_to_le32(simple_strtoul(uuid, NULL, 16));
81e11938eaSJason Hobbs 	memcpy(out, &tmp32, 4);
82e11938eaSJason Hobbs 
83e11938eaSJason Hobbs 	tmp16 = cpu_to_le16(simple_strtoul(uuid + 9, NULL, 16));
84e11938eaSJason Hobbs 	memcpy(out + 4, &tmp16, 2);
85e11938eaSJason Hobbs 
86e11938eaSJason Hobbs 	tmp16 = cpu_to_le16(simple_strtoul(uuid + 14, NULL, 16));
87e11938eaSJason Hobbs 	memcpy(out + 6, &tmp16, 2);
88e11938eaSJason Hobbs 
89e11938eaSJason Hobbs 	tmp16 = cpu_to_be16(simple_strtoul(uuid + 19, NULL, 16));
90e11938eaSJason Hobbs 	memcpy(out + 8, &tmp16, 2);
91e11938eaSJason Hobbs 
92e11938eaSJason Hobbs 	tmp64 = cpu_to_be64(simple_strtoull(uuid + 24, NULL, 16));
93e11938eaSJason Hobbs 	memcpy(out + 10, (char *)&tmp64 + 2, 6);
94*a96a0e61SPrzemyslaw Marczak 
95*a96a0e61SPrzemyslaw Marczak 	return 0;
96*a96a0e61SPrzemyslaw Marczak }
97*a96a0e61SPrzemyslaw Marczak 
98*a96a0e61SPrzemyslaw Marczak void uuid_bin_to_str(unsigned char *uuid, char *str)
99*a96a0e61SPrzemyslaw Marczak {
100*a96a0e61SPrzemyslaw Marczak 	static const u8 le[16] = {3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11,
101*a96a0e61SPrzemyslaw Marczak 				  12, 13, 14, 15};
102*a96a0e61SPrzemyslaw Marczak 	int i;
103*a96a0e61SPrzemyslaw Marczak 
104*a96a0e61SPrzemyslaw Marczak 	for (i = 0; i < 16; i++) {
105*a96a0e61SPrzemyslaw Marczak 		sprintf(str, "%02x", uuid[le[i]]);
106*a96a0e61SPrzemyslaw Marczak 		str += 2;
107*a96a0e61SPrzemyslaw Marczak 		switch (i) {
108*a96a0e61SPrzemyslaw Marczak 		case 3:
109*a96a0e61SPrzemyslaw Marczak 		case 5:
110*a96a0e61SPrzemyslaw Marczak 		case 7:
111*a96a0e61SPrzemyslaw Marczak 		case 9:
112*a96a0e61SPrzemyslaw Marczak 			*str++ = '-';
113*a96a0e61SPrzemyslaw Marczak 			break;
114*a96a0e61SPrzemyslaw Marczak 		}
115*a96a0e61SPrzemyslaw Marczak 	}
116e11938eaSJason Hobbs }
117