xref: /aosp_15_r20/external/coreboot/util/smmstoretool/vs.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "vs.h"
4 
5 #include <limits.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 
10 #include "udk2017.h"
11 #include "utils.h"
12 
get_var_hdr_size(bool auth_vars)13 static size_t get_var_hdr_size(bool auth_vars)
14 {
15 	if (auth_vars)
16 		return sizeof(AUTHENTICATED_VARIABLE_HEADER);
17 	return sizeof(VARIABLE_HEADER);
18 }
19 
vs_load(struct mem_range_t vs_data,bool auth_vars)20 struct var_store_t vs_load(struct mem_range_t vs_data, bool auth_vars)
21 {
22 	uint8_t *var_hdr = vs_data.start;
23 
24 	struct var_store_t vs = {
25 		.auth_vars = auth_vars,
26 		.vars = NULL,
27 	};
28 
29 	struct var_t *last_var = NULL;
30 
31 	const size_t var_hdr_size = get_var_hdr_size(auth_vars);
32 	while (var_hdr + var_hdr_size < vs_data.start + vs_data.length) {
33 		uint16_t start_id;
34 		uint8_t state;
35 		struct var_t var = {0};
36 		uint8_t *var_data = var_hdr;
37 
38 		if (auth_vars) {
39 			const AUTHENTICATED_VARIABLE_HEADER *auth_hdr =
40 				(void *)var_data;
41 
42 			start_id = auth_hdr->StartId;
43 			state = auth_hdr->State;
44 
45 			var.reserved = auth_hdr->Reserved;
46 			var.attrs = auth_hdr->Attributes;
47 			var.name_size = auth_hdr->NameSize;
48 			var.data_size = auth_hdr->DataSize;
49 			var.guid = auth_hdr->VendorGuid;
50 		} else {
51 			const VARIABLE_HEADER *no_auth_hdr = (void *)var_data;
52 
53 			start_id = no_auth_hdr->StartId;
54 			state = no_auth_hdr->State;
55 
56 			var.reserved = no_auth_hdr->Reserved;
57 			var.attrs = no_auth_hdr->Attributes;
58 			var.name_size = no_auth_hdr->NameSize;
59 			var.data_size = no_auth_hdr->DataSize;
60 			var.guid = no_auth_hdr->VendorGuid;
61 		}
62 
63 		var_hdr += HEADER_ALIGN(var_hdr_size +
64 					var.name_size +
65 					var.data_size);
66 
67 		if (start_id != VARIABLE_DATA)
68 			break;
69 
70 		if (state != VAR_ADDED)
71 			continue;
72 
73 		if (var.data_size == UINT32_MAX ||
74 		    var.name_size == UINT32_MAX ||
75 		    var.attrs == UINT32_MAX)
76 			continue;
77 
78 		CHAR16 *name = (void *)(var_data + var_hdr_size);
79 		var.name = xmalloc(var.name_size);
80 		memcpy(var.name, name, var.name_size);
81 
82 		uint8_t *data =
83 			(void *)(var_data + var_hdr_size + var.name_size);
84 		var.data = xmalloc(var.data_size);
85 		memcpy(var.data, data, var.data_size);
86 
87 		struct var_t *var_node = xmalloc(sizeof(*var_node));
88 		*var_node = var;
89 		if (last_var != NULL)
90 			last_var->next = var_node;
91 		else if (vs.vars == NULL)
92 			vs.vars = var_node;
93 		last_var = var_node;
94 	}
95 
96 	return vs;
97 }
98 
store_var(const struct var_t * var,bool auth_vars,uint8_t * data)99 static void store_var(const struct var_t *var, bool auth_vars, uint8_t *data)
100 {
101 	if (auth_vars) {
102 		AUTHENTICATED_VARIABLE_HEADER hdr;
103 		memset(&hdr, 0xff, sizeof(hdr));
104 
105 		hdr.StartId = VARIABLE_DATA;
106 		hdr.State = VAR_ADDED;
107 		hdr.Reserved = var->reserved;
108 		hdr.Attributes = var->attrs;
109 		hdr.VendorGuid = var->guid;
110 		hdr.NameSize = var->name_size;
111 		hdr.DataSize = var->data_size;
112 
113 		memcpy(data, &hdr, sizeof(hdr));
114 		data += sizeof(hdr);
115 	} else {
116 		VARIABLE_HEADER hdr;
117 		memset(&hdr, 0xff, sizeof(hdr));
118 
119 		hdr.StartId = VARIABLE_DATA;
120 		hdr.State = VAR_ADDED;
121 		hdr.Reserved = var->reserved;
122 		hdr.Attributes = var->attrs;
123 		hdr.VendorGuid = var->guid;
124 		hdr.NameSize = var->name_size;
125 		hdr.DataSize = var->data_size;
126 
127 		memcpy(data, &hdr, sizeof(hdr));
128 		data += sizeof(hdr);
129 	}
130 
131 	memcpy(data, var->name, var->name_size);
132 	memcpy(data + var->name_size, var->data, var->data_size);
133 }
134 
vs_store(struct var_store_t * vs,struct mem_range_t vs_data)135 bool vs_store(struct var_store_t *vs, struct mem_range_t vs_data)
136 {
137 	uint8_t *out_data = vs_data.start;
138 
139 	const size_t var_hdr_size = get_var_hdr_size(vs->auth_vars);
140 	for (struct var_t *var = vs->vars; var != NULL; var = var->next) {
141 		const size_t var_size =
142 			var_hdr_size + var->name_size + var->data_size;
143 		if (out_data + var_size > vs_data.start + vs_data.length) {
144 			fprintf(stderr,
145 				"Not enough space to serialize Variable Store.\n");
146 			return false;
147 		}
148 
149 		store_var(var, vs->auth_vars, out_data);
150 		out_data += HEADER_ALIGN(var_size);
151 	}
152 
153 	// The rest is "uninitialized".
154 	memset(out_data, 0xff, vs_data.length - (out_data - vs_data.start));
155 
156 	return true;
157 }
158 
vs_new_var(struct var_store_t * vs)159 struct var_t *vs_new_var(struct var_store_t *vs)
160 {
161 	struct var_t *new_var = xmalloc(sizeof(*new_var));
162 
163 	memset(new_var, 0, sizeof(*new_var));
164 	new_var->attrs = EFI_VARIABLE_NON_VOLATILE
165 				   | EFI_VARIABLE_BOOTSERVICE_ACCESS
166 				   | EFI_VARIABLE_RUNTIME_ACCESS;
167 
168 	struct var_t *var = vs->vars;
169 	if (var == NULL) {
170 		vs->vars = new_var;
171 	} else {
172 		while (var->next != NULL)
173 			var = var->next;
174 		var->next = new_var;
175 	}
176 
177 	return new_var;
178 }
179 
vs_find(struct var_store_t * vs,const char name[],const EFI_GUID * guid)180 struct var_t *vs_find(struct var_store_t *vs,
181 		      const char name[],
182 		      const EFI_GUID *guid)
183 {
184 	size_t name_size;
185 	CHAR16 *uchar_name = to_uchars(name, &name_size);
186 
187 	struct var_t *var;
188 	for (var = vs->vars; var != NULL; var = var->next) {
189 		if (var->name_size != name_size)
190 			continue;
191 		if (memcmp(var->name, uchar_name, name_size) != 0)
192 			continue;
193 		if (memcmp(&var->guid, guid, sizeof(*guid)) != 0)
194 			continue;
195 		break;
196 	}
197 
198 	free(uchar_name);
199 	return var;
200 }
201 
free_var(struct var_t * var)202 static void free_var(struct var_t *var)
203 {
204 	free(var->name);
205 	free(var->data);
206 	free(var);
207 }
208 
vs_delete(struct var_store_t * vs,struct var_t * var)209 void vs_delete(struct var_store_t *vs, struct var_t *var)
210 {
211 	if (vs->vars == var) {
212 		vs->vars = var->next;
213 		free_var(var);
214 		return;
215 	}
216 
217 	for (struct var_t *v = vs->vars; v != NULL; v = v->next) {
218 		if (v->next == var) {
219 			v->next = var->next;
220 			free_var(var);
221 			return;
222 		}
223 	}
224 }
225 
vs_free(struct var_store_t * vs)226 void vs_free(struct var_store_t *vs)
227 {
228 	for (struct var_t *next, *var = vs->vars; var != NULL; var = next) {
229 		next = var->next;
230 		free_var(var);
231 	}
232 }
233