summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/lib/bl_aux_params/bl_aux_params.h103
-rw-r--r--lib/bl_aux_params/bl_aux_params.c33
2 files changed, 136 insertions, 0 deletions
diff --git a/include/lib/bl_aux_params/bl_aux_params.h b/include/lib/bl_aux_params/bl_aux_params.h
new file mode 100644
index 00000000..cfea3956
--- /dev/null
+++ b/include/lib/bl_aux_params/bl_aux_params.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef LIB_BL_AUX_PARAMS_H
+#define LIB_BL_AUX_PARAMS_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/*
+ * This API implements a lightweight parameter passing mechanism that can be
+ * used to pass SoC Firmware configuration data from BL2 to BL31 by platforms or
+ * configurations that do not want to depend on libfdt. It is structured as a
+ * singly-linked list of parameter structures that all share the same common
+ * header but may have different (and differently-sized) structure bodies after
+ * that. The header contains a type field to indicate the parameter type (which
+ * is used to infer the structure length and how to interpret its contents) and
+ * a next pointer which contains the absolute physical address of the next
+ * parameter structure. The next pointer in the last structure block is set to
+ * NULL. The picture below shows how the parameters are kept in memory.
+ *
+ * head of list ---> +----------------+ --+
+ * | type | |
+ * +----------------+ |--> struct bl_aux_param
+ * +----| next | |
+ * | +----------------+ --+
+ * | | parameter data |
+ * | +----------------+
+ * |
+ * +--> +----------------+ --+
+ * | type | |
+ * +----------------+ |--> struct bl_aux_param
+ * NULL <---| next | |
+ * +----------------+ --+
+ * | parameter data |
+ * +----------------+
+ *
+ * Note: The SCTLR_EL3.A bit (Alignment fault check enable) is set in TF-A, so
+ * BL2 must ensure that each parameter struct starts on a 64-bit aligned address
+ * to avoid alignment faults. Parameters may be allocated in any address range
+ * accessible at the time of BL31 handoff (e.g. SRAM, DRAM, SoC-internal scratch
+ * registers, etc.), in particular address ranges that may not be mapped in
+ * BL31's page tables, so the parameter list must be parsed before the MMU is
+ * enabled and any information that is required at a later point should be
+ * deep-copied out into BL31-internal data structures.
+ */
+
+enum bl_aux_param_type {
+ BL_AUX_PARAM_NONE = 0,
+ BL_AUX_PARAM_VENDOR_SPECIFIC_FIRST = 0x1,
+ /* 0x1 - 0x7fffffff can be used by vendor-specific handlers. */
+ BL_AUX_PARAM_VENDOR_SPECIFIC_LAST = 0x7fffffff,
+ BL_AUX_PARAM_GENERIC_FIRST = 0x80000001,
+ BL_AUX_PARAM_COREBOOT_TABLE = BL_AUX_PARAM_GENERIC_FIRST,
+ /* 0x80000001 - 0xffffffff are reserved for the generic handler. */
+ BL_AUX_PARAM_GENERIC_LAST = 0xffffffff,
+ /* Top 32 bits of the type field are reserved for future use. */
+};
+
+/* common header for all BL aux parameters */
+struct bl_aux_param_header {
+ uint64_t type;
+ uint64_t next;
+};
+
+/* commonly useful parameter structures that can be shared by multiple types */
+struct bl_aux_param_uint64 {
+ struct bl_aux_param_header h;
+ uint64_t value;
+};
+
+struct bl_aux_gpio_info {
+ uint8_t polarity;
+ uint8_t direction;
+ uint8_t pull_mode;
+ uint8_t reserved;
+ uint32_t index;
+};
+
+struct bl_aux_param_gpio {
+ struct bl_aux_param_header h;
+ struct bl_aux_gpio_info gpio;
+};
+
+/*
+ * Handler function that handles an individual aux parameter. Return true if
+ * the parameter was handled, and flase if bl_aux_params_parse() should make its
+ * own attempt at handling it (for generic parameters).
+ */
+typedef bool (*bl_aux_param_handler_t)(struct bl_aux_param_header *param);
+
+/*
+ * Interprets head as the start of an aux parameter list, and passes the
+ * parameters individually to handler(). Handles generic parameters directly if
+ * handler() hasn't already done so. If only generic parameters are expected,
+ * handler() can be NULL.
+ */
+void bl_aux_params_parse(u_register_t head,
+ bl_aux_param_handler_t handler);
+
+#endif /* LIB_BL_AUX_PARAMS_H */
diff --git a/lib/bl_aux_params/bl_aux_params.c b/lib/bl_aux_params/bl_aux_params.c
new file mode 100644
index 00000000..7a8115c6
--- /dev/null
+++ b/lib/bl_aux_params/bl_aux_params.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/coreboot.h>
+#include <lib/bl_aux_params/bl_aux_params.h>
+
+void bl_aux_params_parse(u_register_t head,
+ bl_aux_param_handler_t handler)
+{
+ struct bl_aux_param_header *p;
+
+ for (p = (void *)head; p; p = (void *)(uintptr_t)p->next) {
+ if (handler && handler(p))
+ continue;
+
+ switch (p->type) {
+#if COREBOOT
+ case BL_AUX_PARAM_COREBOOT_TABLE:
+ coreboot_table_setup((void *)(uintptr_t)
+ ((struct bl_aux_param_uint64 *)p)->value);
+ break;
+#endif
+ default:
+ ERROR("Ignoring unknown BL aux parameter: 0x%llx",
+ p->type);
+ break;
+ }
+ }
+}