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