1 /* 2 * Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <errno.h> 9 #include <string.h> 10 11 #include <common/debug.h> 12 #include <common/uuid.h> 13 14 /* Return the hex nibble value of a char */ 15 static int8_t hex_val(char hex) 16 { 17 int8_t val = 0; 18 19 if ((hex >= '0') && (hex <= '9')) { 20 val = (int8_t)(hex - '0'); 21 } else if ((hex >= 'a') && (hex <= 'f')) { 22 val = (int8_t)(hex - 'a' + 0xa); 23 } else if ((hex >= 'A') && (hex <= 'F')) { 24 val = (int8_t)(hex - 'A' + 0xa); 25 } else { 26 val = -1; 27 } 28 29 return val; 30 } 31 32 /* 33 * Read hex_src_len hex characters from hex_src, convert to bytes and 34 * store in buffer pointed to by dest 35 */ 36 static int read_hex(uint8_t *dest, char *hex_src, unsigned int hex_src_len) 37 { 38 int8_t nibble; 39 uint8_t byte; 40 41 /* 42 * The string length must be a multiple of 2 to represent an 43 * exact number of bytes. 44 */ 45 assert((hex_src_len % 2U) == 0U); 46 47 for (unsigned int i = 0U; i < (hex_src_len / 2U); i++) { 48 nibble = 0; 49 byte = 0U; 50 51 nibble = hex_val(hex_src[2U * i]); 52 if (nibble < 0) { 53 return -1; 54 } 55 byte = (uint8_t)nibble; 56 byte <<= 4U; 57 58 nibble = hex_val(hex_src[(2U * i) + 1U]); 59 if (nibble < 0) { 60 return -1; 61 } 62 byte |= (uint8_t)nibble; 63 64 *dest = byte; 65 dest++; 66 } 67 68 return 0; 69 } 70 71 /* Parse UUIDs of the form aabbccdd-eeff-4099-8877-665544332211 */ 72 int read_uuid(uint8_t *dest, char *uuid) 73 { 74 int err; 75 uint8_t *dest_start = dest; 76 77 /* Check that we have enough characters */ 78 if (strnlen(uuid, UUID_STRING_LENGTH) != UUID_STRING_LENGTH) { 79 WARN("UUID string is too short\n"); 80 return -EINVAL; 81 } 82 83 /* aabbccdd */ 84 err = read_hex(dest, uuid, 8); 85 uuid += 8; 86 dest += 4; 87 88 /* Check for '-' */ 89 err |= ((*uuid == '-') ? 0 : -1); 90 uuid++; 91 92 /* eeff */ 93 err |= read_hex(dest, uuid, 4); 94 uuid += 4; 95 dest += 2; 96 97 /* Check for '-' */ 98 err |= ((*uuid == '-') ? 0 : -1); 99 uuid++; 100 101 /* 4099 */ 102 err |= read_hex(dest, uuid, 4); 103 uuid += 4; 104 dest += 2; 105 106 /* Check for '-' */ 107 err |= ((*uuid == '-') ? 0 : -1); 108 uuid++; 109 110 /* 8877 */ 111 err |= read_hex(dest, uuid, 4); 112 uuid += 4; 113 dest += 2; 114 115 /* Check for '-' */ 116 err |= ((*uuid == '-') ? 0 : -1); 117 uuid++; 118 119 /* 665544332211 */ 120 err |= read_hex(dest, uuid, 12); 121 uuid += 12; 122 dest += 6; 123 124 if (err < 0) { 125 WARN("Error parsing UUID\n"); 126 /* Clear the buffer on error */ 127 memset((void *)dest_start, '\0', UUID_BYTES_LENGTH * sizeof(uint8_t)); 128 return -EINVAL; 129 } 130 131 return 0; 132 } 133 134 /* 135 * Helper function to check if 2 UUIDs match. 136 */ 137 bool uuid_match(uint32_t *uuid1, uint32_t *uuid2) 138 { 139 return !memcmp(uuid1, uuid2, sizeof(uint32_t) * 4); 140 } 141 142 /* 143 * Helper function to copy from one UUID struct to another. 144 */ 145 void copy_uuid(uint32_t *to_uuid, uint32_t *from_uuid) 146 { 147 to_uuid[0] = from_uuid[0]; 148 to_uuid[1] = from_uuid[1]; 149 to_uuid[2] = from_uuid[2]; 150 to_uuid[3] = from_uuid[3]; 151 } 152 153 bool is_null_uuid(uint32_t *uuid) 154 { 155 return (uuid[0] == 0 && uuid[1] == 0 && 156 uuid[2] == 0 && uuid[3] == 0); 157 } 158