fconf: initial commit

Introduce the Firmware CONfiguration Framework (fconf).

The fconf is an abstraction layer for platform specific data, allowing
a "property" to be queried and a value retrieved without the requesting
entity knowing what backing store is being used to hold the data.

The default backing store used is C structure. If another backing store
has to be used, the platform integrator needs to provide a "populate()"
function to fill the corresponding C structure.
The "populate()" function must be registered to the fconf framework with
the "FCONF_REGISTER_POPULATOR()". This ensures that the function would
be called inside the "fconf_populate()" function.

A two level macro is used as getter:
- the first macro takes 3 parameters and converts it to a function
  call: FCONF_GET_PROPERTY(a,b,c) -> a__b_getter(c).
- the second level defines a__b_getter(c) to the matching C structure,
  variable, array, function, etc..

Ex: Get a Chain of trust property:
    1) FCONF_GET_PROPERY(tbbr, cot, BL2_id) -> tbbr__cot_getter(BL2_id)
    2) tbbr__cot_getter(BL2_id) -> cot_desc_ptr[BL2_id]

Change-Id: Id394001353ed295bc680c3f543af0cf8da549469
Signed-off-by: Louis Mayencourt <louis.mayencourt@arm.com>
diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S
index 6230562..c1338e2 100644
--- a/bl2/bl2.ld.S
+++ b/bl2/bl2.ld.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -46,6 +46,11 @@
         __RODATA_START__ = .;
         *(SORT_BY_ALIGNMENT(.rodata*))
 
+       . = ALIGN(8);
+        __FCONF_POPULATOR_START__ = .;
+        KEEP(*(.fconf_populator))
+        __FCONF_POPULATOR_END__ = .;
+
         /* Ensure 8-byte alignment for descriptors and ensure inclusion */
         . = ALIGN(8);
         __PARSER_LIB_DESCS_START__ = .;
@@ -62,6 +67,11 @@
         *(SORT_BY_ALIGNMENT(.text*))
         *(SORT_BY_ALIGNMENT(.rodata*))
 
+	. = ALIGN(8);
+         __FCONF_POPULATOR_START__ = .;
+         KEEP(*(.fconf_populator))
+         __FCONF_POPULATOR_END__ = .;
+
         /* Ensure 8-byte alignment for descriptors and ensure inclusion */
         . = ALIGN(8);
         __PARSER_LIB_DESCS_START__ = .;
diff --git a/drivers/auth/auth_mod.c b/drivers/auth/auth_mod.c
index 3fb2d1a..91ee1be 100644
--- a/drivers/auth/auth_mod.c
+++ b/drivers/auth/auth_mod.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,6 +16,7 @@
 #include <drivers/auth/auth_mod.h>
 #include <drivers/auth/crypto_mod.h>
 #include <drivers/auth/img_parser_mod.h>
+#include <lib/fconf/fconf_tbbr_getter.h>
 #include <plat/common/platform.h>
 
 /* ASN.1 tags */
@@ -302,9 +303,8 @@
 	const auth_img_desc_t *img_desc = NULL;
 
 	assert(parent_id != NULL);
-
 	/* Get the image descriptor */
-	img_desc = cot_desc_ptr[img_id];
+	img_desc = FCONF_GET_PROPERTY(tbbr, cot, img_id);
 
 	/* Check if the image has no parent (ROT) */
 	if (img_desc->parent == NULL) {
@@ -353,7 +353,7 @@
 	int rc, i;
 
 	/* Get the image descriptor from the chain of trust */
-	img_desc = cot_desc_ptr[img_id];
+	img_desc = FCONF_GET_PROPERTY(tbbr, cot, img_id);
 
 	/* Ask the parser to check the image integrity */
 	rc = img_parser_check_integrity(img_desc->img_type, img_ptr, img_len);
diff --git a/include/lib/fconf/fconf.h b/include/lib/fconf/fconf.h
new file mode 100644
index 0000000..c5f10d2
--- /dev/null
+++ b/include/lib/fconf/fconf.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FCONF_H
+#define FCONF_H
+
+#include <stdint.h>
+
+/* Public API */
+#define FCONF_GET_PROPERTY(a, b, c)	a##__##b##_getter(c)
+
+#define FCONF_REGISTER_POPULATOR(name, callback)				\
+	__attribute__((used, section(".fconf_populator")))			\
+	const struct fconf_populator name##__populator = {			\
+		.info = #name,							\
+		.populate = callback						\
+	};
+
+/*
+ * Populator callback
+ *
+ * This structure are used by the fconf_populate function and should only be
+ * defined by the FCONF_REGISTER_POPULATOR macro.
+ */
+struct fconf_populator {
+	/* Description of the data loaded by the callback */
+	const char *info;
+
+	/* Callback used by fconf_populate function with a provided config dtb.
+	 * Return 0 on success, err_code < 0 otherwise.
+	 */
+	int (*populate)(uintptr_t config);
+};
+
+/* Top level populate function
+ *
+ * This function takes a configuration dtb and calls all the registered
+ * populator callback with it.
+ *
+ *  Panic on error.
+ */
+void fconf_populate(uintptr_t config);
+
+#endif /* FCONF_H */
diff --git a/include/lib/fconf/fconf_tbbr_getter.h b/include/lib/fconf/fconf_tbbr_getter.h
new file mode 100644
index 0000000..fb81e7b
--- /dev/null
+++ b/include/lib/fconf/fconf_tbbr_getter.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FCONF_TBBR_GETTER_H
+#define FCONF_TBBR_GETTER_H
+
+#include <lib/fconf/fconf.h>
+
+/* TBBR related getter */
+#define tbbr__cot_getter(id)	cot_desc_ptr[id]
+
+#endif /* FCONF_TBBR_GETTER_H */
diff --git a/lib/fconf/fconf.c b/lib/fconf/fconf.c
new file mode 100644
index 0000000..387e758
--- /dev/null
+++ b/lib/fconf/fconf.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <lib/fconf/fconf.h>
+#include <libfdt.h>
+#include <platform_def.h>
+
+void fconf_populate(uintptr_t config)
+{
+	assert(config != 0UL);
+
+	/* Check if the pointer to DTB is correct */
+	if (fdt_check_header((void *)config) != 0) {
+		ERROR("FCONF: Invalid DTB file passed for FW_CONFIG\n");
+		panic();
+	}
+
+	INFO("FCONF: Reading firmware configuration file from: 0x%lx\n", config);
+
+	/* Go through all registered populate functions */
+	IMPORT_SYM(struct fconf_populator *, __FCONF_POPULATOR_START__, start);
+	IMPORT_SYM(struct fconf_populator *, __FCONF_POPULATOR_END__, end);
+	const struct fconf_populator *populator;
+
+	for (populator = start; populator != end; populator++) {
+		assert((populator->info != NULL) && (populator->populate != NULL));
+
+		INFO("FCONF: Reading firmware configuration information for: %s\n", populator->info);
+		if (populator->populate(config) != 0) {
+			/* TODO: handle property miss */
+			panic();
+		}
+	}
+}
diff --git a/lib/fconf/fconf.mk b/lib/fconf/fconf.mk
new file mode 100644
index 0000000..0813c73
--- /dev/null
+++ b/lib/fconf/fconf.mk
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Add Firmware Configuration files
+FCONF_SOURCES		:=	lib/fconf/fconf.c
+
+BL1_SOURCES		+=	${FCONF_SOURCES}
+BL2_SOURCES		+=	${FCONF_SOURCES}
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 9f4bc21..abf2f91 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -198,6 +198,9 @@
 				plat/arm/common/arm_err.c			\
 				plat/arm/common/arm_io_storage.c
 
+# Firmware Configuration Framework sources
+include lib/fconf/fconf.mk
+
 # Add `libfdt` and Arm common helpers required for Dynamic Config
 include lib/libfdt/libfdt.mk
 
@@ -270,7 +273,7 @@
     # Include common TBB sources
     AUTH_SOURCES	:=	drivers/auth/auth_mod.c				\
 				drivers/auth/crypto_mod.c			\
-				drivers/auth/img_parser_mod.c			\
+				drivers/auth/img_parser_mod.c
 
     # Include the selected chain of trust sources.
     ifeq (${COT},tbbr)