blob: 7245e8590bd7fa493b9d548a137e6a92a3530dd7 [file] [log] [blame]
// 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 <opal.h>
#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);