[RFC,RESEND,07/10] keystore: add opal_set_variable runtime service

Message ID 20180801234042.6740-8-erichte@linux.ibm.com
State New
Headers show
Series
  • Initial Implementation of Secure Boot Key Management support
Related show

Checks

Context Check Description
snowpatch_ozlabs/apply_patch success master/apply_patch Successfully applied

Commit Message

Eric Richter Aug. 1, 2018, 11:40 p.m.
The opal_set_variable runtime service operates the same way for the active
bank and update queue; it updates an existing variable name's associated
data with the supplied data blob if the requested name exists. If the
requested name does not exist, it appends a new entry in the list.

NOTE: This runtime service does not do any size checks, and is the
likely candidate to do some form of size checking. Since we are holding
the keys in a sparse structure in memory, this service should probably
either use a routine to calculate the current total size, or a total
size value should be maintained either in the list head or globally.

Signed-off-by: Eric Richter <erichte@linux.ibm.com>
---
 libstb/keystore.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

Patch

diff --git a/libstb/keystore.c b/libstb/keystore.c
index 8e19dbb6..8f825f8e 100644
--- a/libstb/keystore.c
+++ b/libstb/keystore.c
@@ -87,6 +87,66 @@  found:
 opal_call(OPAL_GET_VARIABLE, opal_get_variable, 4);
 
 
+static int64_t opal_set_variable(uint64_t k_varname, uint64_t k_vardata, uint64_t varsize, uint64_t section)
+{
+	char *varname = (char*) k_varname;
+	char *vardata = (char*) k_vardata;
+
+	struct keystore_variable *var = NULL;
+
+	struct list_head *bank;
+
+	CHECK_KEYSTORE_READY;
+
+	bank = GET_BANK(section);
+
+	list_for_each(bank, var, link) {
+		if (!strcmp(varname, var->name)) {
+			goto found;
+		}
+	}
+
+	var = (struct keystore_variable *) malloc(sizeof(struct keystore_variable));
+	if (!var) {
+		prlog(PR_ERR, "Failed to allocate new variable\n");
+		return OPAL_NO_MEM;
+	}
+
+	var->name_size = strlen(varname) + 1;
+	var->name = malloc(var->name_size);
+	var->name[var->name_size] = '\0'; // Ensure print-friendly NULL terminator
+	if (!var->name) {
+		prlog(PR_ERR, "Failed to allocate new variable's name\n");
+		return OPAL_NO_MEM;
+	}
+
+	memcpy(var->name, varname, var->name_size);
+	var->data = NULL;
+
+	// Add to the list before moving to the shared behavior portion
+	list_add_tail(bank, &var->link);
+
+found:
+	// Clear old data if this is not a new variable.
+	if (var->data)
+		free(var->data);
+
+	var->data_size = varsize;
+	var->data = malloc(var->data_size);
+	if (!var->data) {
+		prlog(PR_ERR, "Failed to allocate new variable's data\n");
+		// TODO: we should probably clean up the linked list node if there is an error
+		//    maybe we should try allocating data before freeing the old?
+		return OPAL_NO_MEM;
+	}
+
+	memcpy(var->data, vardata, var->data_size);
+
+	return OPAL_SUCCESS;
+}
+opal_call(OPAL_SET_VARIABLE, opal_set_variable, 4);
+
+
 int keystore_init(void)
 {
 	int rc;