1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
// 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);
|