[Skiboot] [RFC PATCH RESEND 08/10] keystore: add opal_get_next_variable runtime service

Eric Richter erichte at linux.ibm.com
Thu Aug 2 09:40:40 AEST 2018


The opal_get_next_variable runtime service allows the caller to iterate
through a bank, and receive the name and optionally the size of the
variable. Each call to opal_get_next_variable will return the next item
in the list until the end is reached, where the varname will be set to
NULL, and OPAL_EMPTY is returned. Since this runtime service maintains
its own state, the caller must be aware of when this function is called,
and to OR the section with START_OVER if they wish to reset.

NOTE: This runtime service is already slated for a rewrite!
I kept this version here since it is a perfect example of reacting to
unforseen implementation issues. An alternate implementation has been
proposed that takes an additional argument: the name of the previous. This
allows for the the caller to maintain the state instead, allowing multiple
calls to this service from multiple threads/locations without requiring
synchronization.

NOTE #2: This commit also introduces a few macros from upstream ccan that
are not in the version included in skiboot. Since the proposed rewrite of
this function would no longer need the macros, consider them irrelevant to
this commit other than to make it compile.

Signed-off-by: Eric Richter <erichte at linux.ibm.com>
---
 libstb/keystore.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 libstb/keystore.h | 19 +++++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/libstb/keystore.c b/libstb/keystore.c
index 8f825f8e..0ddabf5f 100644
--- a/libstb/keystore.c
+++ b/libstb/keystore.c
@@ -147,6 +147,57 @@ found:
 opal_call(OPAL_SET_VARIABLE, opal_set_variable, 4);
 
 
+static int64_t opal_get_next_variable(uint64_t k_varname, uint64_t k_size, uint64_t section)
+{
+	static struct keystore_variable *active_prev = NULL;
+	static struct keystore_variable *update_prev = NULL;
+	struct keystore_variable **prev; // TODO: replace this with a switching macro?
+	struct list_head *bank;
+
+	uint64_t *size = (uint64_t *) k_size;
+
+	CHECK_KEYSTORE_READY;
+
+	// Operate on each bank separately, but we can alias the value to make it easier
+	switch(section & (~START_OVER)) {
+		case ACTIVE_BANK:  prev = &active_prev; break;
+		case UPDATE_QUEUE: prev = &update_prev; break;
+		default: return OPAL_PARAMETER;
+	}
+
+	if (section & START_OVER) {
+		*prev = NULL;
+	}
+
+	// TODO: This may not be needed anymore if the above is doing the check
+	bank = GET_BANK(section);
+	if (!bank) {
+		return OPAL_PARAMETER;
+	}
+
+	// If this is the first (fresh) call
+	if (!(*prev)) {
+		*prev = list_top(bank, struct keystore_variable, link);
+	}
+	// Catch subsequent calls, and incremenet the pointer
+	else {
+		*prev = list_next(bank, *prev, link);
+	}
+
+	// End of the list, or list is empty
+	if (!(*prev)) {
+		return OPAL_EMPTY;
+	}
+
+	strcpy((char*) k_varname, (*prev)->name);
+	if (size)
+		*size = (*prev)->data_size;
+
+	return OPAL_SUCCESS;
+}
+opal_call(OPAL_GET_NEXT_VARIABLE, opal_get_next_variable, 3);
+
+
 int keystore_init(void)
 {
 	int rc;
diff --git a/libstb/keystore.h b/libstb/keystore.h
index e2eb296c..eaaeb1dd 100644
--- a/libstb/keystore.h
+++ b/libstb/keystore.h
@@ -35,4 +35,23 @@ struct keystore_variable {
 	char *data;
 };
 
+
+// TODO: Eventually not depend on these macros here
+#define list_typeof(var) typeof(var)
+
+static inline void *list_entry_or_null(const struct list_head *h,
+				       const struct list_node *n,
+				       size_t off)
+{
+	if (n == &h->n)
+		return NULL;
+	return (char *)n - off;
+}
+
+#define list_next(h, i, member)						\
+	((list_typeof(i))list_entry_or_null(list_debug(h),		\
+					    (i)->member.next,		\
+					    list_off_var_((i), member)))
+
+
 #endif /* __KEYSTORE_H */
-- 
2.14.4



More information about the Skiboot mailing list