xref: /rk3399_rockchip-uboot/lib/uuid.c (revision d718ded056eefb6239bd2e0a57b7f6d99c6e9e4b)
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>
8a96a0e61SPrzemyslaw Marczak #include <errno.h>
9a96a0e61SPrzemyslaw Marczak #include <common.h>
10*d718ded0SPrzemyslaw Marczak #include <asm/io.h>
11*d718ded0SPrzemyslaw Marczak #include <part_efi.h>
12*d718ded0SPrzemyslaw Marczak #include <malloc.h>
13e11938eaSJason Hobbs 
14e11938eaSJason Hobbs /*
15a96a0e61SPrzemyslaw Marczak  * UUID - Universally Unique IDentifier - 128 bits unique number.
16a96a0e61SPrzemyslaw Marczak  *        There are 5 versions and one variant of UUID defined by RFC4122
17a96a0e61SPrzemyslaw Marczak  *        specification. Depends on version uuid number base on a time,
18a96a0e61SPrzemyslaw Marczak  *        host name, MAC address or random data.
19e11938eaSJason Hobbs  *
20a96a0e61SPrzemyslaw Marczak  * UUID binary format (16 bytes):
21a96a0e61SPrzemyslaw Marczak  *
22a96a0e61SPrzemyslaw Marczak  * 4B-2B-2B-2B-6B (big endian - network byte order)
23a96a0e61SPrzemyslaw Marczak  *
24a96a0e61SPrzemyslaw Marczak  * UUID string is 36 length of characters (36 bytes):
25e11938eaSJason Hobbs  *
26e11938eaSJason Hobbs  * 0        9    14   19   24
27e11938eaSJason Hobbs  * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
28a96a0e61SPrzemyslaw Marczak  *    be     be   be   be       be
29a96a0e61SPrzemyslaw Marczak  *
30a96a0e61SPrzemyslaw Marczak  * where x is a hexadecimal character. Fields are separated by '-'s.
31a96a0e61SPrzemyslaw Marczak  * When converting to a binary UUID, le means the field should be converted
32a96a0e61SPrzemyslaw Marczak  * to little endian and be means it should be converted to big endian.
33a96a0e61SPrzemyslaw Marczak  *
34a96a0e61SPrzemyslaw Marczak  * UUID is also used as GUID (Globally Unique Identifier) with the same binary
35a96a0e61SPrzemyslaw Marczak  * format but it differs in string format like below.
36a96a0e61SPrzemyslaw Marczak  *
37a96a0e61SPrzemyslaw Marczak  * GUID:
38a96a0e61SPrzemyslaw Marczak  * 0        9    14   19   24
39a96a0e61SPrzemyslaw Marczak  * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
40e11938eaSJason Hobbs  *    le     le   le   be       be
41a96a0e61SPrzemyslaw Marczak  *
42a96a0e61SPrzemyslaw Marczak  * GUID is used e.g. in GPT (GUID Partition Table) as a partiions unique id.
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 
62*d718ded0SPrzemyslaw Marczak 	if (i != UUID_STR_LEN || !valid)
63e11938eaSJason Hobbs 		return 0;
64e11938eaSJason Hobbs 
65e11938eaSJason Hobbs 	return 1;
66e11938eaSJason Hobbs }
67e11938eaSJason Hobbs 
68*d718ded0SPrzemyslaw Marczak /*
69*d718ded0SPrzemyslaw Marczak  * uuid_str_to_bin() - convert string UUID or GUID to big endian binary data.
70*d718ded0SPrzemyslaw Marczak  *
71*d718ded0SPrzemyslaw Marczak  * @param uuid_str - pointer to UUID or GUID string [37B]
72*d718ded0SPrzemyslaw Marczak  * @param uuid_bin - pointer to allocated array for big endian output [16B]
73*d718ded0SPrzemyslaw Marczak  * @str_format     - UUID string format: 0 - UUID; 1 - GUID
74*d718ded0SPrzemyslaw Marczak  */
75*d718ded0SPrzemyslaw Marczak int uuid_str_to_bin(char *uuid_str, unsigned char *uuid_bin, int str_format)
76e11938eaSJason Hobbs {
77e11938eaSJason Hobbs 	uint16_t tmp16;
78e11938eaSJason Hobbs 	uint32_t tmp32;
79e11938eaSJason Hobbs 	uint64_t tmp64;
80e11938eaSJason Hobbs 
81*d718ded0SPrzemyslaw Marczak 	if (!uuid_str_valid(uuid_str))
82a96a0e61SPrzemyslaw Marczak 		return -EINVAL;
83a96a0e61SPrzemyslaw Marczak 
84*d718ded0SPrzemyslaw Marczak 	if (str_format == UUID_STR_FORMAT_STD) {
85*d718ded0SPrzemyslaw Marczak 		tmp32 = cpu_to_be32(simple_strtoul(uuid_str, NULL, 16));
86*d718ded0SPrzemyslaw Marczak 		memcpy(uuid_bin, &tmp32, 4);
87e11938eaSJason Hobbs 
88*d718ded0SPrzemyslaw Marczak 		tmp16 = cpu_to_be16(simple_strtoul(uuid_str + 9, NULL, 16));
89*d718ded0SPrzemyslaw Marczak 		memcpy(uuid_bin + 4, &tmp16, 2);
90e11938eaSJason Hobbs 
91*d718ded0SPrzemyslaw Marczak 		tmp16 = cpu_to_be16(simple_strtoul(uuid_str + 14, NULL, 16));
92*d718ded0SPrzemyslaw Marczak 		memcpy(uuid_bin + 6, &tmp16, 2);
93*d718ded0SPrzemyslaw Marczak 	} else {
94*d718ded0SPrzemyslaw Marczak 		tmp32 = cpu_to_le32(simple_strtoul(uuid_str, NULL, 16));
95*d718ded0SPrzemyslaw Marczak 		memcpy(uuid_bin, &tmp32, 4);
96e11938eaSJason Hobbs 
97*d718ded0SPrzemyslaw Marczak 		tmp16 = cpu_to_le16(simple_strtoul(uuid_str + 9, NULL, 16));
98*d718ded0SPrzemyslaw Marczak 		memcpy(uuid_bin + 4, &tmp16, 2);
99e11938eaSJason Hobbs 
100*d718ded0SPrzemyslaw Marczak 		tmp16 = cpu_to_le16(simple_strtoul(uuid_str + 14, NULL, 16));
101*d718ded0SPrzemyslaw Marczak 		memcpy(uuid_bin + 6, &tmp16, 2);
102*d718ded0SPrzemyslaw Marczak 	}
103e11938eaSJason Hobbs 
104*d718ded0SPrzemyslaw Marczak 	tmp16 = cpu_to_be16(simple_strtoul(uuid_str + 19, NULL, 16));
105*d718ded0SPrzemyslaw Marczak 	memcpy(uuid_bin + 8, &tmp16, 2);
106*d718ded0SPrzemyslaw Marczak 
107*d718ded0SPrzemyslaw Marczak 	tmp64 = cpu_to_be64(simple_strtoull(uuid_str + 24, NULL, 16));
108*d718ded0SPrzemyslaw Marczak 	memcpy(uuid_bin + 10, (char *)&tmp64 + 2, 6);
109a96a0e61SPrzemyslaw Marczak 
110a96a0e61SPrzemyslaw Marczak 	return 0;
111a96a0e61SPrzemyslaw Marczak }
112a96a0e61SPrzemyslaw Marczak 
113*d718ded0SPrzemyslaw Marczak /*
114*d718ded0SPrzemyslaw Marczak  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
115*d718ded0SPrzemyslaw Marczak  *
116*d718ded0SPrzemyslaw Marczak  * @param uuid_bin - pointer to binary data of UUID (big endian) [16B]
117*d718ded0SPrzemyslaw Marczak  * @param uuid_str - pointer to allocated array for output string [37B]
118*d718ded0SPrzemyslaw Marczak  * @str_format     - UUID string format: 0 - UUID; 1 - GUID
119*d718ded0SPrzemyslaw Marczak  */
120*d718ded0SPrzemyslaw Marczak void uuid_bin_to_str(unsigned char *uuid_bin, char *uuid_str, int str_format)
121a96a0e61SPrzemyslaw Marczak {
122*d718ded0SPrzemyslaw Marczak 	const u8 uuid_char_order[UUID_BIN_LEN] = {0, 1, 2, 3, 4, 5, 6, 7, 8,
123*d718ded0SPrzemyslaw Marczak 						  9, 10, 11, 12, 13, 14, 15};
124*d718ded0SPrzemyslaw Marczak 	const u8 guid_char_order[UUID_BIN_LEN] = {3, 2, 1, 0, 5, 4, 7, 6, 8,
125*d718ded0SPrzemyslaw Marczak 						  9, 10, 11, 12, 13, 14, 15};
126*d718ded0SPrzemyslaw Marczak 	const u8 *char_order;
127a96a0e61SPrzemyslaw Marczak 	int i;
128a96a0e61SPrzemyslaw Marczak 
129*d718ded0SPrzemyslaw Marczak 	/*
130*d718ded0SPrzemyslaw Marczak 	 * UUID and GUID bin data - always in big endian:
131*d718ded0SPrzemyslaw Marczak 	 * 4B-2B-2B-2B-6B
132*d718ded0SPrzemyslaw Marczak 	 * be be be be be
133*d718ded0SPrzemyslaw Marczak 	 */
134*d718ded0SPrzemyslaw Marczak 	if (str_format == UUID_STR_FORMAT_STD)
135*d718ded0SPrzemyslaw Marczak 		char_order = uuid_char_order;
136*d718ded0SPrzemyslaw Marczak 	else
137*d718ded0SPrzemyslaw Marczak 		char_order = guid_char_order;
138*d718ded0SPrzemyslaw Marczak 
139a96a0e61SPrzemyslaw Marczak 	for (i = 0; i < 16; i++) {
140*d718ded0SPrzemyslaw Marczak 		sprintf(uuid_str, "%02x", uuid_bin[char_order[i]]);
141*d718ded0SPrzemyslaw Marczak 		uuid_str += 2;
142a96a0e61SPrzemyslaw Marczak 		switch (i) {
143a96a0e61SPrzemyslaw Marczak 		case 3:
144a96a0e61SPrzemyslaw Marczak 		case 5:
145a96a0e61SPrzemyslaw Marczak 		case 7:
146a96a0e61SPrzemyslaw Marczak 		case 9:
147*d718ded0SPrzemyslaw Marczak 			*uuid_str++ = '-';
148a96a0e61SPrzemyslaw Marczak 			break;
149a96a0e61SPrzemyslaw Marczak 		}
150a96a0e61SPrzemyslaw Marczak 	}
151e11938eaSJason Hobbs }
152