1 /* 2 * SPDX-License-Identifier: GPL-2.0-or-later 3 * 4 * uefi vars device - helper functions for ucs2 strings and tracing 5 */ 6 #include "qemu/osdep.h" 7 #include "system/dma.h" 8 9 #include "hw/uefi/var-service.h" 10 11 #include "trace/trace-hw_uefi.h" 12 13 /* ------------------------------------------------------------------ */ 14 15 /* 16 * string helper functions. 17 * 18 * Most of the time uefi ucs2 strings are NULL-terminated, except 19 * sometimes when they are not (for example in variable policies). 20 */ 21 22 gboolean uefi_str_is_valid(const uint16_t *str, size_t len, 23 gboolean must_be_null_terminated) 24 { 25 size_t pos = 0; 26 27 for (;;) { 28 if (pos == len) { 29 if (must_be_null_terminated) { 30 return false; 31 } else { 32 return true; 33 } 34 } 35 switch (str[pos]) { 36 case 0: 37 /* end of string */ 38 return true; 39 case 0xd800 ... 0xdfff: 40 /* reject surrogates */ 41 return false; 42 default: 43 /* char is good, check next */ 44 break; 45 } 46 pos++; 47 } 48 } 49 50 size_t uefi_strlen(const uint16_t *str, size_t len) 51 { 52 size_t pos = 0; 53 54 for (;;) { 55 if (pos == len) { 56 return pos; 57 } 58 if (str[pos] == 0) { 59 return pos; 60 } 61 pos++; 62 } 63 } 64 65 gboolean uefi_str_equal_ex(const uint16_t *a, size_t alen, 66 const uint16_t *b, size_t blen, 67 gboolean wildcards_in_a) 68 { 69 size_t pos = 0; 70 71 alen = alen / 2; 72 blen = blen / 2; 73 for (;;) { 74 if (pos == alen && pos == blen) { 75 return true; 76 } 77 if (pos == alen && b[pos] == 0) { 78 return true; 79 } 80 if (pos == blen && a[pos] == 0) { 81 return true; 82 } 83 if (pos == alen || pos == blen) { 84 return false; 85 } 86 if (a[pos] == 0 && b[pos] == 0) { 87 return true; 88 } 89 90 if (wildcards_in_a && a[pos] == '#') { 91 if (!isxdigit(b[pos])) { 92 return false; 93 } 94 } else { 95 if (a[pos] != b[pos]) { 96 return false; 97 } 98 } 99 pos++; 100 } 101 } 102 103 gboolean uefi_str_equal(const uint16_t *a, size_t alen, 104 const uint16_t *b, size_t blen) 105 { 106 return uefi_str_equal_ex(a, alen, b, blen, false); 107 } 108 109 char *uefi_ucs2_to_ascii(const uint16_t *ucs2, uint64_t ucs2_size) 110 { 111 char *str = g_malloc0(ucs2_size / 2 + 1); 112 int i; 113 114 for (i = 0; i * 2 < ucs2_size; i++) { 115 if (ucs2[i] == 0) { 116 break; 117 } 118 if (ucs2[i] < 128) { 119 str[i] = ucs2[i]; 120 } else { 121 str[i] = '?'; 122 } 123 } 124 str[i] = 0; 125 return str; 126 } 127 128 /* ------------------------------------------------------------------ */ 129 /* time helper functions */ 130 131 int uefi_time_compare(efi_time *a, efi_time *b) 132 { 133 if (a->year < b->year) { 134 return -1; 135 } 136 if (a->year > b->year) { 137 return 1; 138 } 139 140 if (a->month < b->month) { 141 return -1; 142 } 143 if (a->month > b->month) { 144 return 1; 145 } 146 147 if (a->day < b->day) { 148 return -1; 149 } 150 if (a->day > b->day) { 151 return 1; 152 } 153 154 if (a->hour < b->hour) { 155 return -1; 156 } 157 if (a->hour > b->hour) { 158 return 1; 159 } 160 161 if (a->minute < b->minute) { 162 return -1; 163 } 164 if (a->minute > b->minute) { 165 return 1; 166 } 167 168 if (a->second < b->second) { 169 return -1; 170 } 171 if (a->second > b->second) { 172 return 1; 173 } 174 175 if (a->nanosecond < b->nanosecond) { 176 return -1; 177 } 178 if (a->nanosecond > b->nanosecond) { 179 return 1; 180 } 181 182 return 0; 183 } 184 185 /* ------------------------------------------------------------------ */ 186 /* tracing helper functions */ 187 188 void uefi_trace_variable(const char *action, QemuUUID guid, 189 const uint16_t *name, uint64_t name_size) 190 { 191 QemuUUID be = qemu_uuid_bswap(guid); 192 char *str_uuid = qemu_uuid_unparse_strdup(&be); 193 char *str_name = uefi_ucs2_to_ascii(name, name_size); 194 195 trace_uefi_variable(action, str_name, name_size, str_uuid); 196 197 g_free(str_name); 198 g_free(str_uuid); 199 } 200 201 void uefi_trace_status(const char *action, efi_status status) 202 { 203 switch (status) { 204 case EFI_SUCCESS: 205 trace_uefi_status(action, "success"); 206 break; 207 case EFI_INVALID_PARAMETER: 208 trace_uefi_status(action, "invalid parameter"); 209 break; 210 case EFI_UNSUPPORTED: 211 trace_uefi_status(action, "unsupported"); 212 break; 213 case EFI_BAD_BUFFER_SIZE: 214 trace_uefi_status(action, "bad buffer size"); 215 break; 216 case EFI_BUFFER_TOO_SMALL: 217 trace_uefi_status(action, "buffer too small"); 218 break; 219 case EFI_WRITE_PROTECTED: 220 trace_uefi_status(action, "write protected"); 221 break; 222 case EFI_OUT_OF_RESOURCES: 223 trace_uefi_status(action, "out of resources"); 224 break; 225 case EFI_NOT_FOUND: 226 trace_uefi_status(action, "not found"); 227 break; 228 case EFI_ACCESS_DENIED: 229 trace_uefi_status(action, "access denied"); 230 break; 231 case EFI_ALREADY_STARTED: 232 trace_uefi_status(action, "already started"); 233 break; 234 case EFI_SECURITY_VIOLATION: 235 trace_uefi_status(action, "security violation"); 236 break; 237 default: 238 trace_uefi_status(action, "unknown error"); 239 break; 240 } 241 } 242