// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later /* Copyright 2019 IBM Corp. */ #ifndef pr_fmt #define pr_fmt(fmt) "SECVAR_API: " fmt #endif #include #include "secvar.h" static int64_t opal_secvar_get(const char *key, uint64_t key_len, void *data, uint64_t *data_size) { struct secvar *var; int64_t rc = OPAL_SUCCESS; if (!secvar_enabled) return OPAL_UNSUPPORTED; if (!secvar_ready) return OPAL_RESOURCE; if (!key) return OPAL_PARAMETER; if (key_len == 0) return OPAL_PARAMETER; // Data size must be set, data is optional for size query if (!data_size) return OPAL_PARAMETER; var = find_secvar(key, key_len, &variable_bank); if (!var) return OPAL_EMPTY; // Variable not found, bail early if (!data) rc = OPAL_SUCCESS; else if (*data_size < var->data_size) rc = OPAL_PARTIAL; else memcpy(data, var->data, var->data_size); *data_size = var->data_size; return rc; } opal_call(OPAL_SECVAR_GET, opal_secvar_get, 4); static int64_t opal_secvar_get_next(char *key, uint64_t *key_len, uint64_t key_buf_size) { struct secvar *var; if (!secvar_enabled) return OPAL_UNSUPPORTED; if (!secvar_ready) return OPAL_RESOURCE; if (!key_len) return OPAL_PARAMETER; if (key_buf_size == 0) return OPAL_PARAMETER; if (*key_len > SECVAR_MAX_KEY_LEN) return OPAL_PARAMETER; if (*key_len > key_buf_size) return OPAL_PARAMETER; if (!key) return OPAL_PARAMETER; if (!is_key_empty(key, *key_len)) { var = find_secvar(key, *key_len, &variable_bank); if (!var) return OPAL_PARAMETER; var = list_next(&variable_bank, var, link); } else { var = list_top(&variable_bank, struct secvar, link); } if (!var) return OPAL_EMPTY; if (key_buf_size < var->key_len) { *key_len = var->key_len; return OPAL_PARTIAL; } *key_len = var->key_len; memcpy(key, var->key, var->key_len); return OPAL_SUCCESS; } opal_call(OPAL_SECVAR_GET_NEXT, opal_secvar_get_next, 3); static int64_t opal_secvar_enqueue_update(const char *key, uint64_t key_len, void *data, uint64_t data_size) { struct secvar *var; if (!secvar_enabled) return OPAL_UNSUPPORTED; if (!secvar_ready) return OPAL_RESOURCE; if (!secvar_storage.write_bank) return OPAL_HARDWARE; if (!key) return OPAL_PARAMETER; if (key_len == 0) return OPAL_PARAMETER; if (key_len > SECVAR_MAX_KEY_LEN) return OPAL_PARAMETER; if ((!data) && (data_size != 0)) return OPAL_PARAMETER; if (data_size > secvar_storage.max_var_size) return OPAL_PARAMETER; // Key should not be empty if (is_key_empty(key, key_len)) return OPAL_PARAMETER; var = find_secvar(key, key_len, &update_bank); // Unstage an update if (data_size == 0) { if (!var) return OPAL_EMPTY; list_del(&var->link); dealloc_secvar(var); goto out; } if (var) { list_del(&var->link); // Realloc var if too small if (var->data_size < data_size) { if (realloc_secvar(var, data_size)) return OPAL_NO_MEM; } else { memset(var->data, 0x00, var->data_size); } } else { var = alloc_secvar(key_len, data_size); if (!var) return OPAL_NO_MEM; } memcpy(var->key, key, key_len); var->key_len = key_len; memcpy(var->data, data, data_size); var->data_size = data_size; list_add_tail(&update_bank, &var->link); out: if (secvar_storage.write_bank(&update_bank, SECVAR_UPDATE_BANK)) return OPAL_HARDWARE; else return OPAL_SUCCESS; } opal_call(OPAL_SECVAR_ENQUEUE_UPDATE, opal_secvar_enqueue_update, 4);