Lines Matching +full:- +full:- +full:-

2  * SPDX-License-Identifier: GPL-2.0-or-later
4 * uefi vars device - EfiSmmVariableProtocol implementation
7 #include "qemu/error-report.h"
11 #include "hw/uefi/var-service.h"
12 #include "hw/uefi/var-service-api.h"
13 #include "hw/uefi/var-service-edk2.h"
15 #include "trace/trace-hw_uefi.h"
27 .name = "uefi-time",
41 .name = "uefi-variable",
59 QTAILQ_FOREACH(var, &uv->variables, next) { in uefi_vars_find_variable()
60 if (!uefi_str_equal(var->name, var->name_size, in uefi_vars_find_variable()
64 if (!qemu_uuid_is_equal(&var->guid, &guid)) { in uefi_vars_find_variable()
67 if (!var->data_size) { in uefi_vars_find_variable()
83 var->guid = guid; in add_variable()
84 var->name = g_malloc(name_size); in add_variable()
85 memcpy(var->name, name, name_size); in add_variable()
86 var->name_size = name_size; in add_variable()
87 var->attributes = attributes; in add_variable()
89 var->attributes &= ~EFI_VARIABLE_APPEND_WRITE; in add_variable()
91 QTAILQ_INSERT_TAIL(&uv->variables, var, next); in add_variable()
101 QTAILQ_REMOVE(&uv->variables, var, next); in del_variable()
102 g_free(var->data); in del_variable()
103 g_free(var->name); in del_variable()
104 g_free(var->digest); in del_variable()
113 size += var->name_size; in variable_size()
114 size += var->data_size; in variable_size()
115 size += var->digest_size; in variable_size()
130 uv->used_storage -= variable_size(old_var); in uefi_vars_set_variable()
135 new_var->data = g_malloc(data_size); in uefi_vars_set_variable()
136 new_var->data_size = data_size; in uefi_vars_set_variable()
137 memcpy(new_var->data, data, data_size); in uefi_vars_set_variable()
138 uv->used_storage += variable_size(new_var); in uefi_vars_set_variable()
145 QTAILQ_FOREACH_SAFE(var, &uv->variables, next, n) { in uefi_vars_clear_volatile()
146 if (var->attributes & EFI_VARIABLE_NON_VOLATILE) { in uefi_vars_clear_volatile()
149 uv->used_storage -= variable_size(var); in uefi_vars_clear_volatile()
158 QTAILQ_FOREACH_SAFE(var, &uv->variables, next, n) { in uefi_vars_clear_all()
161 uv->used_storage = 0; in uefi_vars_clear_all()
168 uv->used_storage = 0; in uefi_vars_update_storage()
169 QTAILQ_FOREACH(var, &uv->variables, next) { in uefi_vars_update_storage()
170 uv->used_storage += variable_size(var); in uefi_vars_update_storage()
176 if (!uv->exit_boot_service) { in check_access()
177 if (!(var->attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)) { in check_access()
181 if (!(var->attributes & EFI_VARIABLE_RUNTIME_ACCESS)) { in check_access()
200 if (new_var->attributes & ~EFI_VARIABLE_ATTRIBUTE_SUPPORTED) { in check_update()
209 if (old_var->attributes != new_var->attributes) { in check_update()
242 uefi_vars_siglist_parse(&siglist, old_var->data, old_var->data_size); in append_write()
243 uefi_vars_siglist_parse(&siglist, new_var->data, new_var->data_size); in append_write()
249 g_free(new_var->data); in append_write()
250 new_var->data = data; in append_write()
251 new_var->data_size = size; in append_write()
259 mvar->status = status; in uefi_vars_mm_error()
273 if (mhdr->length < length) { in uefi_vars_mm_get_variable()
277 if (va->name_size > uv->max_storage || in uefi_vars_mm_get_variable()
278 va->data_size > uv->max_storage) { in uefi_vars_mm_get_variable()
283 if (uadd64_overflow(length, va->name_size, &length)) { in uefi_vars_mm_get_variable()
286 if (mhdr->length < length) { in uefi_vars_mm_get_variable()
290 if (!uefi_str_is_valid(name, va->name_size, true)) { in uefi_vars_mm_get_variable()
294 uefi_trace_variable(__func__, va->guid, name, va->name_size); in uefi_vars_mm_get_variable()
296 var = uefi_vars_find_variable(uv, va->guid, name, va->name_size); in uefi_vars_mm_get_variable()
306 data = func + sizeof(*va) + va->name_size; in uefi_vars_mm_get_variable()
307 if (uadd64_overflow(length, va->data_size, &length)) { in uefi_vars_mm_get_variable()
310 if (uv->buf_size < length) { in uefi_vars_mm_get_variable()
314 va->attributes = var->attributes; in uefi_vars_mm_get_variable()
315 if (va->data_size < var->data_size) { in uefi_vars_mm_get_variable()
316 va->data_size = var->data_size; in uefi_vars_mm_get_variable()
317 length -= va->data_size; in uefi_vars_mm_get_variable()
318 mvar->status = EFI_BUFFER_TOO_SMALL; in uefi_vars_mm_get_variable()
320 va->data_size = var->data_size; in uefi_vars_mm_get_variable()
321 memcpy(data, var->data, var->data_size); in uefi_vars_mm_get_variable()
322 mvar->status = EFI_SUCCESS; in uefi_vars_mm_get_variable()
337 if (mhdr->length < length) { in uefi_vars_mm_get_next_variable()
341 if (nv->name_size > uv->max_storage) { in uefi_vars_mm_get_next_variable()
346 if (uadd64_overflow(length, nv->name_size, &length)) { in uefi_vars_mm_get_next_variable()
349 if (mhdr->length < length) { in uefi_vars_mm_get_next_variable()
353 if (!uefi_str_is_valid(name, nv->name_size, true)) { in uefi_vars_mm_get_next_variable()
357 if (uefi_strlen(name, nv->name_size) == 0) { in uefi_vars_mm_get_next_variable()
358 /* empty string -> first */ in uefi_vars_mm_get_next_variable()
359 var = QTAILQ_FIRST(&uv->variables); in uefi_vars_mm_get_next_variable()
364 var = uefi_vars_find_variable(uv, nv->guid, name, nv->name_size); in uefi_vars_mm_get_next_variable()
376 length = sizeof(*mvar) + sizeof(*nv) + var->name_size; in uefi_vars_mm_get_next_variable()
377 if (uv->buf_size < length) { in uefi_vars_mm_get_next_variable()
381 nv->guid = var->guid; in uefi_vars_mm_get_next_variable()
382 nv->name_size = var->name_size; in uefi_vars_mm_get_next_variable()
383 memcpy(name, var->name, var->name_size); in uefi_vars_mm_get_next_variable()
384 mvar->status = EFI_SUCCESS; in uefi_vars_mm_get_next_variable()
391 if (!old_var->digest || in uefi_vars_mm_digest_compare()
392 !new_var->digest || in uefi_vars_mm_digest_compare()
393 !old_var->digest_size || in uefi_vars_mm_digest_compare()
394 !new_var->digest_size) { in uefi_vars_mm_digest_compare()
399 if (old_var->digest_size != new_var->digest_size) { in uefi_vars_mm_digest_compare()
403 if (memcmp(old_var->digest, new_var->digest, in uefi_vars_mm_digest_compare()
404 old_var->digest_size) != 0) { in uefi_vars_mm_digest_compare()
424 if (mhdr->length < length) { in uefi_vars_mm_set_variable()
428 if (va->name_size > uv->max_storage || in uefi_vars_mm_set_variable()
429 va->data_size > uv->max_storage) { in uefi_vars_mm_set_variable()
434 if (uadd64_overflow(length, va->name_size, &length)) { in uefi_vars_mm_set_variable()
437 if (mhdr->length < length) { in uefi_vars_mm_set_variable()
441 data = func + sizeof(*va) + va->name_size; in uefi_vars_mm_set_variable()
442 if (uadd64_overflow(length, va->data_size, &length)) { in uefi_vars_mm_set_variable()
445 if (mhdr->length < length) { in uefi_vars_mm_set_variable()
449 g_assert(va->name_size < G_MAXUINT32); in uefi_vars_mm_set_variable()
450 g_assert(va->data_size < G_MAXUINT32); in uefi_vars_mm_set_variable()
452 if (!uefi_str_is_valid(name, va->name_size, true)) { in uefi_vars_mm_set_variable()
456 uefi_trace_variable(__func__, va->guid, name, va->name_size); in uefi_vars_mm_set_variable()
458 old_var = uefi_vars_find_variable(uv, va->guid, name, va->name_size); in uefi_vars_mm_set_variable()
459 if (va->data_size) { in uefi_vars_mm_set_variable()
460 new_var = add_variable(uv, va->guid, name, va->name_size, in uefi_vars_mm_set_variable()
461 va->attributes); in uefi_vars_mm_set_variable()
462 if (va->attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) { in uefi_vars_mm_set_variable()
465 mvar->status = EFI_UNSUPPORTED; in uefi_vars_mm_set_variable()
467 } else if (va->attributes & in uefi_vars_mm_set_variable()
471 mvar->status = status; in uefi_vars_mm_set_variable()
475 if (uefi_time_compare(&old_var->time, &new_var->time) > 0) { in uefi_vars_mm_set_variable()
477 mvar->status = EFI_SECURITY_VIOLATION; in uefi_vars_mm_set_variable()
480 if (old_var->digest_size || new_var->digest_size) { in uefi_vars_mm_set_variable()
482 mvar->status = EFI_SECURITY_VIOLATION; in uefi_vars_mm_set_variable()
488 new_var->data = g_malloc(va->data_size); in uefi_vars_mm_set_variable()
489 memcpy(new_var->data, data, va->data_size); in uefi_vars_mm_set_variable()
490 new_var->data_size = va->data_size; in uefi_vars_mm_set_variable()
492 if (!new_var->data) { in uefi_vars_mm_set_variable()
502 /* delete non-existing variable -> nothing to do */ in uefi_vars_mm_set_variable()
503 mvar->status = EFI_SUCCESS; in uefi_vars_mm_set_variable()
510 mvar->status = status; in uefi_vars_mm_set_variable()
514 if (va->attributes & EFI_VARIABLE_APPEND_WRITE && old_var && new_var) { in uefi_vars_mm_set_variable()
517 mvar->status = EFI_UNSUPPORTED; in uefi_vars_mm_set_variable()
524 new_storage = uv->used_storage; in uefi_vars_mm_set_variable()
526 new_storage -= variable_size(old_var); in uefi_vars_mm_set_variable()
531 if (new_storage > uv->max_storage) { in uefi_vars_mm_set_variable()
532 mvar->status = EFI_OUT_OF_RESOURCES; in uefi_vars_mm_set_variable()
537 ? new_var->attributes in uefi_vars_mm_set_variable()
538 : old_var->attributes; in uefi_vars_mm_set_variable()
542 uv->used_storage = new_storage; in uefi_vars_mm_set_variable()
552 mvar->status = EFI_SUCCESS; in uefi_vars_mm_set_variable()
567 if (uv->buf_size < length) { in uefi_vars_mm_variable_info()
571 vi->max_storage_size = uv->max_storage; in uefi_vars_mm_variable_info()
572 vi->free_storage_size = uv->max_storage - uv->used_storage; in uefi_vars_mm_variable_info()
573 vi->max_variable_size = uv->max_storage >> 2; in uefi_vars_mm_variable_info()
574 vi->attributes = 0; in uefi_vars_mm_variable_info()
576 mvar->status = EFI_SUCCESS; in uefi_vars_mm_variable_info()
588 if (uv->buf_size < length) { in uefi_vars_mm_get_payload_size()
592 ps->payload_size = uv->buf_size; in uefi_vars_mm_get_payload_size()
593 mvar->status = EFI_SUCCESS; in uefi_vars_mm_get_payload_size()
607 if (mhdr->length < length) { in uefi_vars_mm_lock_variable()
612 if (uadd64_overflow(length, lv->name_size, &length)) { in uefi_vars_mm_lock_variable()
615 if (mhdr->length < length) { in uefi_vars_mm_lock_variable()
619 uefi_trace_variable(__func__, lv->guid, name, lv->name_size); in uefi_vars_mm_lock_variable()
621 pe = g_malloc0(sizeof(*pe) + lv->name_size); in uefi_vars_mm_lock_variable()
622 pe->version = VARIABLE_POLICY_ENTRY_REVISION; in uefi_vars_mm_lock_variable()
623 pe->size = sizeof(*pe) + lv->name_size; in uefi_vars_mm_lock_variable()
624 pe->offset_to_name = sizeof(*pe); in uefi_vars_mm_lock_variable()
625 pe->namespace = lv->guid; in uefi_vars_mm_lock_variable()
626 pe->min_size = 0; in uefi_vars_mm_lock_variable()
627 pe->max_size = UINT32_MAX; in uefi_vars_mm_lock_variable()
628 pe->attributes_must_have = 0; in uefi_vars_mm_lock_variable()
629 pe->attributes_cant_have = 0; in uefi_vars_mm_lock_variable()
630 pe->lock_policy_type = VARIABLE_POLICY_TYPE_LOCK_NOW; in uefi_vars_mm_lock_variable()
632 dest = (void *)pe + pe->offset_to_name; in uefi_vars_mm_lock_variable()
633 memcpy(dest, name, lv->name_size); in uefi_vars_mm_lock_variable()
638 mvar->status = EFI_SUCCESS; in uefi_vars_mm_lock_variable()
646 "get-variable", in uefi_vars_mm_vars_proto()
647 "get-next-variable-name", in uefi_vars_mm_vars_proto()
648 "set-variable", in uefi_vars_mm_vars_proto()
649 "query-variable-info", in uefi_vars_mm_vars_proto()
650 "ready-to-boot", in uefi_vars_mm_vars_proto()
651 "exit-boot-service", in uefi_vars_mm_vars_proto()
652 "get-statistics", in uefi_vars_mm_vars_proto()
653 "lock-variable", in uefi_vars_mm_vars_proto()
654 "var-check-prop-set", in uefi_vars_mm_vars_proto()
655 "var-check-prop-get", in uefi_vars_mm_vars_proto()
656 "get-payload-size", in uefi_vars_mm_vars_proto()
657 "init-runtime-cache-contect", in uefi_vars_mm_vars_proto()
658 "sync-runtime-cache", in uefi_vars_mm_vars_proto()
659 "get-runtime-cache-info", in uefi_vars_mm_vars_proto()
664 mm_header *mhdr = (mm_header *) uv->buffer; in uefi_vars_mm_vars_proto()
665 mm_variable *mvar = (mm_variable *) (uv->buffer + sizeof(*mhdr)); in uefi_vars_mm_vars_proto()
666 void *func = (uv->buffer + sizeof(*mhdr) + sizeof(*mvar)); in uefi_vars_mm_vars_proto()
668 if (mhdr->length < sizeof(*mvar)) { in uefi_vars_mm_vars_proto()
672 fname = mvar->function < ARRAY_SIZE(fnames) in uefi_vars_mm_vars_proto()
673 ? fnames[mvar->function] in uefi_vars_mm_vars_proto()
677 switch (mvar->function) { in uefi_vars_mm_vars_proto()
703 trace_uefi_event("ready-to-boot"); in uefi_vars_mm_vars_proto()
704 uv->ready_to_boot = true; in uefi_vars_mm_vars_proto()
709 trace_uefi_event("exit-boot-service"); in uefi_vars_mm_vars_proto()
710 uv->exit_boot_service = true; in uefi_vars_mm_vars_proto()
719 if (mhdr->length < length) { in uefi_vars_mm_vars_proto()
720 mvar->status = EFI_BUFFER_TOO_SMALL; in uefi_vars_mm_vars_proto()
723 uefi_trace_status(__func__, mvar->status); in uefi_vars_mm_vars_proto()