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