1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright 2011 Calxeda, Inc. 4 * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> 5 * 6 * Authors: 7 * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> 8 */ 9 10#define LOG_CATEGOT LOGC_CORE 11 12#include <command.h> 13#include <efi_api.h> 14#include <env.h> 15#include <rand.h> 16#include <time.h> 17#include <uuid.h> 18#include <linux/ctype.h> 19#include <errno.h> 20#include <asm/io.h> 21#include <part_efi.h> 22#include <malloc.h> 23#include <dm/uclass.h> 24#include <rng.h> 25 26int 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 44 if (i != UUID_STR_LEN || !valid) 45 return 0; 46 47 return 1; 48} 49 50static const struct { 51 const char *string; 52 efi_guid_t guid; 53} list_guid[] = { 54#ifdef CONFIG_PARTITION_TYPE_GUID 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}, 62 {"lvm", PARTITION_LINUX_LVM_GUID}, 63 {"u-boot-env", PARTITION_U_BOOT_ENVIRONMENT}, 64 {"cros-kern", PARTITION_CROS_KERNEL}, 65 {"cros-root", PARTITION_CROS_ROOT}, 66 {"cros-fw", PARTITION_CROS_FIRMWARE}, 67 {"cros-rsrv", PARTITION_CROS_RESERVED}, 68#endif 69#if defined(CONFIG_CMD_EFIDEBUG) || defined(CONFIG_EFI) 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 }, 150 { 151 "TCG2", 152 EFI_TCG2_PROTOCOL_GUID, 153 }, 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 }, 179 { 180 "SMBIOS3 table", 181 SMBIOS3_TABLE_GUID, 182 }, 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 }, 191 { 192 "EFI Conformance Profiles Table", 193 EFI_CONFORMANCE_PROFILES_TABLE_GUID, 194 }, 195#ifdef CONFIG_EFI_RISCV_BOOT_PROTOCOL 196 { 197 "RISC-V Boot", 198 RISCV_EFI_BOOT_PROTOCOL_GUID, 199 }, 200#endif 201#endif /* CONFIG_CMD_EFIDEBUG */ 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 226#if defined(CONFIG_CMD_EFIDEBUG) || defined(CONFIG_EFI) 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 234}; 235 236int 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 249const char *uuid_guid_get_str(const unsigned char *guid_bin) 250{ 251 int i; 252 253 for (i = 0; i < ARRAY_SIZE(list_guid); i++) { 254 if (!memcmp(list_guid[i].guid.b, guid_bin, 16)) { 255 return list_guid[i].string; 256 } 257 } 258 return NULL; 259} 260 261int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin, 262 int str_format) 263{ 264 uint16_t tmp16; 265 uint32_t tmp32; 266 uint64_t tmp64; 267 268 if (!uuid_str_valid(uuid_str)) { 269 log_debug("not valid\n"); 270#ifdef CONFIG_PARTITION_TYPE_GUID 271 if (!uuid_guid_get_bin(uuid_str, uuid_bin)) 272 return 0; 273#endif 274 return -EINVAL; 275 } 276 277 if (str_format == UUID_STR_FORMAT_STD) { 278 tmp32 = cpu_to_be32(hextoul(uuid_str, NULL)); 279 memcpy(uuid_bin, &tmp32, 4); 280 281 tmp16 = cpu_to_be16(hextoul(uuid_str + 9, NULL)); 282 memcpy(uuid_bin + 4, &tmp16, 2); 283 284 tmp16 = cpu_to_be16(hextoul(uuid_str + 14, NULL)); 285 memcpy(uuid_bin + 6, &tmp16, 2); 286 } else { 287 tmp32 = cpu_to_le32(hextoul(uuid_str, NULL)); 288 memcpy(uuid_bin, &tmp32, 4); 289 290 tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL)); 291 memcpy(uuid_bin + 4, &tmp16, 2); 292 293 tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL)); 294 memcpy(uuid_bin + 6, &tmp16, 2); 295 } 296 297 tmp16 = cpu_to_be16(hextoul(uuid_str + 19, NULL)); 298 memcpy(uuid_bin + 8, &tmp16, 2); 299 300 tmp64 = cpu_to_be64(simple_strtoull(uuid_str + 24, NULL, 16)); 301 memcpy(uuid_bin + 10, (char *)&tmp64 + 2, 6); 302 303 return 0; 304} 305 306int 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 333void uuid_bin_to_str(const unsigned char *uuid_bin, char *uuid_str, 334 int str_format) 335{ 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; 341 const char *format; 342 int i; 343 344 /* 345 * UUID and GUID bin data - always in big endian: 346 * 4B-2B-2B-2B-6B 347 * be be be be be 348 */ 349 if (str_format & UUID_STR_FORMAT_GUID) 350 char_order = guid_char_order; 351 else 352 char_order = uuid_char_order; 353 if (str_format & UUID_STR_UPPER_CASE) 354 format = "%02X"; 355 else 356 format = "%02x"; 357 358 for (i = 0; i < 16; i++) { 359 sprintf(uuid_str, format, uuid_bin[char_order[i]]); 360 uuid_str += 2; 361 switch (i) { 362 case 3: 363 case 5: 364 case 7: 365 case 9: 366 *uuid_str++ = '-'; 367 break; 368 } 369 } 370} 371 372#if defined(CONFIG_RANDOM_UUID) || defined(CONFIG_CMD_UUID) 373void gen_rand_uuid(unsigned char *uuid_bin) 374{ 375 u32 ptr[4]; 376 struct uuid *uuid = (struct uuid *)ptr; 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); 383 if (!ret) { 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()); 393 394 /* Set all fields randomly */ 395 for (i = 0; i < 4; i++) 396 ptr[i] = rand(); 397 398 clrsetbits_be16(&uuid->time_hi_and_version, 399 UUID_VERSION_MASK, 400 UUID_VERSION << UUID_VERSION_SHIFT); 401 402 clrsetbits_8(&uuid->clock_seq_hi_and_reserved, 403 UUID_VARIANT_MASK, 404 UUID_VARIANT << UUID_VARIANT_SHIFT); 405 406 memcpy(uuid_bin, uuid, 16); 407} 408 409void 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} 419 420#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CMD_UUID) 421int do_uuid(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 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 439 env_set(argv[1], uuid); 440 441 return CMD_RET_SUCCESS; 442} 443 444U_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 452U_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); 459#endif /* CONFIG_CMD_UUID */ 460#endif /* CONFIG_RANDOM_UUID || CONFIG_CMD_UUID */ 461