master
c 344 lines 9.56 KB
Raw
1 /*
2 * SPDX-License-Identifier: GPL-2.0-or-later
3 *
4 * uefi vars device
5 */
6 #include "qemu/osdep.h"
7 #include "qemu/crc32c.h"
8 #include "qemu/error-report.h"
9 #include "system/dma.h"
10 #include "migration/vmstate.h"
11
12 #include "hw/uefi/var-service.h"
13 #include "hw/uefi/var-service-api.h"
14 #include "hw/uefi/var-service-edk2.h"
15
16 #include "trace.h"
17
18 static int uefi_vars_pre_load(void *opaque)
19 {
20 uefi_vars_state *uv = opaque;
21
22 uefi_vars_clear_all(uv);
23 uefi_vars_policies_clear(uv);
24 g_free(uv->buffer);
25 return 0;
26 }
27
28 static int uefi_vars_post_load(void *opaque, int version_id)
29 {
30 uefi_vars_state *uv = opaque;
31
32 if (uv->buf_size > MAX_BUFFER_SIZE) {
33 error_report("invalid buffer size");
34 return -1;
35 }
36 uv->buffer = g_malloc(uv->buf_size);
37
38 uefi_vars_update_storage(uv);
39 if (uv->used_storage > uv->max_storage) {
40 error_report("out of variable memory (%" PRId64 " > %" PRId64 ")",
41 uv->used_storage, uv->max_storage);
42 return -1;
43 }
44
45 uefi_vars_json_save(uv);
46 return 0;
47 }
48
49 const VMStateDescription vmstate_uefi_vars = {
50 .name = "uefi-vars",
51 .pre_load = uefi_vars_pre_load,
52 .post_load = uefi_vars_post_load,
53 .fields = (VMStateField[]) {
54 VMSTATE_UINT16(sts, uefi_vars_state),
55 VMSTATE_UINT32(buf_size, uefi_vars_state),
56 VMSTATE_UINT32(buf_addr_lo, uefi_vars_state),
57 VMSTATE_UINT32(buf_addr_hi, uefi_vars_state),
58 VMSTATE_UINT32(pio_xfer_offset, uefi_vars_state),
59 VMSTATE_VBUFFER_ALLOC_UINT32(pio_xfer_buffer, uefi_vars_state,
60 0, NULL, buf_size),
61 VMSTATE_BOOL(end_of_dxe, uefi_vars_state),
62 VMSTATE_BOOL(ready_to_boot, uefi_vars_state),
63 VMSTATE_BOOL(exit_boot_service, uefi_vars_state),
64 VMSTATE_BOOL(policy_locked, uefi_vars_state),
65 VMSTATE_UINT64(used_storage, uefi_vars_state),
66 VMSTATE_QTAILQ_V(variables, uefi_vars_state, 0,
67 vmstate_uefi_variable, uefi_variable, next),
68 VMSTATE_QTAILQ_V(var_policies, uefi_vars_state, 0,
69 vmstate_uefi_var_policy, uefi_var_policy, next),
70 VMSTATE_END_OF_LIST()
71 },
72 };
73
74 static uint32_t uefi_vars_cmd_mm(uefi_vars_state *uv, bool dma_mode)
75 {
76 hwaddr dma;
77 mm_header *mhdr;
78 uint64_t size;
79 uint32_t retval;
80
81 dma = uv->buf_addr_lo | ((hwaddr)uv->buf_addr_hi << 32);
82 mhdr = (mm_header *) uv->buffer;
83
84 if (!uv->buffer || uv->buf_size < sizeof(*mhdr)) {
85 return UEFI_VARS_STS_ERR_BAD_BUFFER_SIZE;
86 }
87
88 /* read header */
89 if (dma_mode) {
90 dma_memory_read(&address_space_memory, dma,
91 uv->buffer, sizeof(*mhdr),
92 MEMTXATTRS_UNSPECIFIED);
93 } else {
94 memcpy(uv->buffer, uv->pio_xfer_buffer, sizeof(*mhdr));
95 }
96
97 if (uadd64_overflow(sizeof(*mhdr), mhdr->length, &size)) {
98 return UEFI_VARS_STS_ERR_BAD_BUFFER_SIZE;
99 }
100 if (uv->buf_size < size) {
101 return UEFI_VARS_STS_ERR_BAD_BUFFER_SIZE;
102 }
103
104 /* read buffer (excl header) */
105 if (dma_mode) {
106 dma_memory_read(&address_space_memory, dma + sizeof(*mhdr),
107 uv->buffer + sizeof(*mhdr), mhdr->length,
108 MEMTXATTRS_UNSPECIFIED);
109 } else {
110 memcpy(uv->buffer + sizeof(*mhdr),
111 uv->pio_xfer_buffer + sizeof(*mhdr),
112 mhdr->length);
113 }
114 memset(uv->buffer + size, 0, uv->buf_size - size);
115
116 uefi_vars_pcap_request(uv, uv->buffer, size);
117
118 /* dispatch */
119 if (qemu_uuid_is_equal(&mhdr->guid, &EfiSmmVariableProtocolGuid)) {
120 retval = uefi_vars_mm_vars_proto(uv);
121
122 } else if (qemu_uuid_is_equal(&mhdr->guid, &VarCheckPolicyLibMmiHandlerGuid)) {
123 retval = uefi_vars_mm_check_policy_proto(uv);
124
125 } else if (qemu_uuid_is_equal(&mhdr->guid, &EfiEndOfDxeEventGroupGuid)) {
126 trace_uefi_event("end-of-dxe");
127 uv->end_of_dxe = true;
128 retval = UEFI_VARS_STS_SUCCESS;
129
130 } else if (qemu_uuid_is_equal(&mhdr->guid, &EfiEventReadyToBootGuid)) {
131 trace_uefi_event("ready-to-boot");
132 uv->ready_to_boot = true;
133 retval = UEFI_VARS_STS_SUCCESS;
134
135 } else if (qemu_uuid_is_equal(&mhdr->guid, &EfiEventExitBootServicesGuid)) {
136 trace_uefi_event("exit-boot-service");
137 uv->exit_boot_service = true;
138 retval = UEFI_VARS_STS_SUCCESS;
139
140 } else {
141 retval = UEFI_VARS_STS_ERR_NOT_SUPPORTED;
142 }
143
144 uefi_vars_pcap_reply(uv, uv->buffer, sizeof(*mhdr) + mhdr->length);
145
146 /* write buffer */
147 if (dma_mode) {
148 dma_memory_write(&address_space_memory, dma,
149 uv->buffer, sizeof(*mhdr) + mhdr->length,
150 MEMTXATTRS_UNSPECIFIED);
151 } else {
152 memcpy(uv->pio_xfer_buffer,
153 uv->buffer, sizeof(*mhdr) + mhdr->length);
154 }
155
156 return retval;
157 }
158
159 static void uefi_vars_soft_reset(uefi_vars_state *uv)
160 {
161 g_free(uv->buffer);
162 uv->buffer = NULL;
163 uv->buf_size = 0;
164 uv->buf_addr_lo = 0;
165 uv->buf_addr_hi = 0;
166 }
167
168 void uefi_vars_hard_reset(uefi_vars_state *uv)
169 {
170 trace_uefi_hard_reset();
171 uefi_vars_soft_reset(uv);
172
173 uv->end_of_dxe = false;
174 uv->ready_to_boot = false;
175 uv->exit_boot_service = false;
176 uv->policy_locked = false;
177
178 uefi_vars_clear_volatile(uv);
179 uefi_vars_policies_clear(uv);
180 uefi_vars_auth_init(uv);
181
182 uefi_vars_pcap_reset(uv);
183 }
184
185 static uint32_t uefi_vars_cmd(uefi_vars_state *uv, uint32_t cmd)
186 {
187 switch (cmd) {
188 case UEFI_VARS_CMD_RESET:
189 uefi_vars_soft_reset(uv);
190 return UEFI_VARS_STS_SUCCESS;
191 case UEFI_VARS_CMD_DMA_MM:
192 return uefi_vars_cmd_mm(uv, true);
193 case UEFI_VARS_CMD_PIO_MM:
194 return uefi_vars_cmd_mm(uv, false);
195 case UEFI_VARS_CMD_PIO_ZERO_OFFSET:
196 uv->pio_xfer_offset = 0;
197 return UEFI_VARS_STS_SUCCESS;
198 default:
199 return UEFI_VARS_STS_ERR_NOT_SUPPORTED;
200 }
201 }
202
203 static uint64_t uefi_vars_read(void *opaque, hwaddr addr, unsigned size)
204 {
205 uefi_vars_state *uv = opaque;
206 uint64_t retval = -1;
207 void *xfer_ptr;
208
209 trace_uefi_reg_read(addr, size);
210
211 switch (addr) {
212 case UEFI_VARS_REG_MAGIC:
213 retval = UEFI_VARS_MAGIC_VALUE;
214 break;
215 case UEFI_VARS_REG_CMD_STS:
216 retval = uv->sts;
217 break;
218 case UEFI_VARS_REG_BUFFER_SIZE:
219 retval = uv->buf_size;
220 break;
221 case UEFI_VARS_REG_DMA_BUFFER_ADDR_LO:
222 retval = uv->buf_addr_lo;
223 break;
224 case UEFI_VARS_REG_DMA_BUFFER_ADDR_HI:
225 retval = uv->buf_addr_hi;
226 break;
227 case UEFI_VARS_REG_PIO_BUFFER_TRANSFER:
228 if (uv->pio_xfer_offset + size > uv->buf_size) {
229 retval = 0;
230 break;
231 }
232 xfer_ptr = uv->pio_xfer_buffer + uv->pio_xfer_offset;
233 switch (size) {
234 case 1:
235 retval = *(uint8_t *)xfer_ptr;
236 break;
237 case 2:
238 retval = *(uint16_t *)xfer_ptr;
239 break;
240 case 4:
241 retval = *(uint32_t *)xfer_ptr;
242 break;
243 case 8:
244 retval = *(uint64_t *)xfer_ptr;
245 break;
246 }
247 uv->pio_xfer_offset += size;
248 break;
249 case UEFI_VARS_REG_PIO_BUFFER_CRC32C:
250 if (uv->pio_xfer_offset > uv->buf_size) {
251 retval = 0;
252 break;
253 }
254 retval = crc32c(0xffffffff, uv->pio_xfer_buffer, uv->pio_xfer_offset);
255 break;
256 case UEFI_VARS_REG_FLAGS:
257 retval = 0;
258 if (uv->use_pio) {
259 retval |= UEFI_VARS_FLAG_USE_PIO;
260 }
261 }
262 return retval;
263 }
264
265 static void uefi_vars_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
266 {
267 uefi_vars_state *uv = opaque;
268 void *xfer_ptr;
269
270 trace_uefi_reg_write(addr, val, size);
271
272 switch (addr) {
273 case UEFI_VARS_REG_CMD_STS:
274 uv->sts = uefi_vars_cmd(uv, val);
275 break;
276 case UEFI_VARS_REG_BUFFER_SIZE:
277 if (val > MAX_BUFFER_SIZE) {
278 val = MAX_BUFFER_SIZE;
279 }
280 uv->buf_size = val;
281 g_free(uv->buffer);
282 g_free(uv->pio_xfer_buffer);
283 uv->buffer = g_malloc0(uv->buf_size);
284 uv->pio_xfer_buffer = g_malloc0(uv->buf_size);
285 break;
286 case UEFI_VARS_REG_DMA_BUFFER_ADDR_LO:
287 uv->buf_addr_lo = val;
288 break;
289 case UEFI_VARS_REG_DMA_BUFFER_ADDR_HI:
290 uv->buf_addr_hi = val;
291 break;
292 case UEFI_VARS_REG_PIO_BUFFER_TRANSFER:
293 if (uv->pio_xfer_offset + size > uv->buf_size) {
294 break;
295 }
296 xfer_ptr = uv->pio_xfer_buffer + uv->pio_xfer_offset;
297 switch (size) {
298 case 1:
299 *(uint8_t *)xfer_ptr = val;
300 break;
301 case 2:
302 *(uint16_t *)xfer_ptr = val;
303 break;
304 case 4:
305 *(uint32_t *)xfer_ptr = val;
306 break;
307 case 8:
308 *(uint64_t *)xfer_ptr = val;
309 break;
310 }
311 uv->pio_xfer_offset += size;
312 break;
313 case UEFI_VARS_REG_PIO_BUFFER_CRC32C:
314 case UEFI_VARS_REG_FLAGS:
315 default:
316 break;
317 }
318 }
319
320 static const MemoryRegionOps uefi_vars_ops = {
321 .read = uefi_vars_read,
322 .write = uefi_vars_write,
323 .endianness = DEVICE_LITTLE_ENDIAN,
324 .impl = {
325 .min_access_size = 2,
326 .max_access_size = 4,
327 },
328 };
329
330 void uefi_vars_init(Object *obj, uefi_vars_state *uv)
331 {
332 QTAILQ_INIT(&uv->variables);
333 QTAILQ_INIT(&uv->var_policies);
334 uv->jsonfd = -1;
335 memory_region_init_io(&uv->mr, obj, &uefi_vars_ops, uv,
336 "uefi-vars", UEFI_VARS_REGS_SIZE);
337 }
338
339 void uefi_vars_realize(uefi_vars_state *uv, Error **errp)
340 {
341 uefi_vars_json_init(uv, errp);
342 uefi_vars_json_load(uv, errp);
343 uefi_vars_pcap_init(uv, errp);
344 }