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