arch/arm64: Support FEAT_CCIDX
[coreboot2.git] / util / smmstoretool / vs.c
bloba1167ca2de74fb867b8ba01d767e133e23740ff5
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include "vs.h"
5 #include <limits.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
10 #include "udk2017.h"
11 #include "utils.h"
13 static size_t get_var_hdr_size(bool auth_vars)
15 if (auth_vars)
16 return sizeof(AUTHENTICATED_VARIABLE_HEADER);
17 return sizeof(VARIABLE_HEADER);
20 struct var_store_t vs_load(struct mem_range_t vs_data, bool auth_vars)
22 uint8_t *var_hdr = vs_data.start;
24 struct var_store_t vs = {
25 .auth_vars = auth_vars,
26 .vars = NULL,
29 struct var_t *last_var = NULL;
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;
38 if (auth_vars) {
39 const AUTHENTICATED_VARIABLE_HEADER *auth_hdr =
40 (void *)var_data;
42 start_id = auth_hdr->StartId;
43 state = auth_hdr->State;
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;
53 start_id = no_auth_hdr->StartId;
54 state = no_auth_hdr->State;
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;
63 var_hdr += HEADER_ALIGN(var_hdr_size +
64 var.name_size +
65 var.data_size);
67 if (start_id != VARIABLE_DATA)
68 break;
70 if (state != VAR_ADDED)
71 continue;
73 if (var.data_size == UINT32_MAX ||
74 var.name_size == UINT32_MAX ||
75 var.attrs == UINT32_MAX)
76 continue;
78 CHAR16 *name = (void *)(var_data + var_hdr_size);
79 var.name = xmalloc(var.name_size);
80 memcpy(var.name, name, var.name_size);
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);
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;
96 return vs;
99 static void store_var(const struct var_t *var, bool auth_vars, uint8_t *data)
101 if (auth_vars) {
102 AUTHENTICATED_VARIABLE_HEADER hdr;
103 memset(&hdr, 0xff, sizeof(hdr));
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;
113 memcpy(data, &hdr, sizeof(hdr));
114 data += sizeof(hdr);
115 } else {
116 VARIABLE_HEADER hdr;
117 memset(&hdr, 0xff, sizeof(hdr));
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;
127 memcpy(data, &hdr, sizeof(hdr));
128 data += sizeof(hdr);
131 memcpy(data, var->name, var->name_size);
132 memcpy(data + var->name_size, var->data, var->data_size);
135 bool vs_store(struct var_store_t *vs, struct mem_range_t vs_data)
137 uint8_t *out_data = vs_data.start;
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;
149 store_var(var, vs->auth_vars, out_data);
150 out_data += HEADER_ALIGN(var_size);
153 // The rest is "uninitialized".
154 memset(out_data, 0xff, vs_data.length - (out_data - vs_data.start));
156 return true;
159 struct var_t *vs_new_var(struct var_store_t *vs)
161 struct var_t *new_var = xmalloc(sizeof(*new_var));
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;
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;
177 return new_var;
180 struct var_t *vs_find(struct var_store_t *vs,
181 const char name[],
182 const EFI_GUID *guid)
184 size_t name_size;
185 CHAR16 *uchar_name = to_uchars(name, &name_size);
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;
198 free(uchar_name);
199 return var;
202 static void free_var(struct var_t *var)
204 free(var->name);
205 free(var->data);
206 free(var);
209 void vs_delete(struct var_store_t *vs, struct var_t *var)
211 if (vs->vars == var) {
212 vs->vars = var->next;
213 free_var(var);
214 return;
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;
226 void vs_free(struct var_store_t *vs)
228 for (struct var_t *next, *var = vs->vars; var != NULL; var = next) {
229 next = var->next;
230 free_var(var);