157 lines
3.4 KiB
C
157 lines
3.4 KiB
C
// 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);
|