@@ -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;
@@ -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 */
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@linux.ibm.com> --- libstb/keystore.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ libstb/keystore.h | 19 +++++++++++++++++++ 2 files changed, 70 insertions(+)