binman: Add a library to access binman entries

SPL and TPL can access information about binman entries using link-time
symbols but this is not available in U-Boot proper. Of course it could be
made available, but the intention is to just read the device tree.

Add support for this, so that U-Boot can locate entries.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
diff --git a/lib/Kconfig b/lib/Kconfig
index 965cf7b..d040a87 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -7,6 +7,16 @@
 	  This is used by SoC platforms which do not have built-in ELM
 	  hardware engine required for BCH ECC correction.
 
+config BINMAN_FDT
+	bool "Allow access to binman information in the device tree"
+	depends on BINMAN && OF_CONTROL
+	default y
+	help
+	  This enables U-Boot to access information about binman entries,
+	  stored in the device tree in a binman node. Typical uses are to
+	  locate entries in the firmware image. See binman.h for the available
+	  functionality.
+
 config CC_OPTIMIZE_LIBS_FOR_SPEED
 	bool "Optimize libraries for speed"
 	help
diff --git a/lib/Makefile b/lib/Makefile
index 1fb650c..7a713a5 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -21,6 +21,7 @@
 obj-y += crypto/
 
 obj-$(CONFIG_AES) += aes.o
+obj-$(CONFIG_$(SPL_TPL_)BINMAN_FDT) += binman.o
 
 ifndef API_BUILD
 ifneq ($(CONFIG_UT_UNICODE)$(CONFIG_EFI_LOADER),)
diff --git a/lib/binman.c b/lib/binman.c
new file mode 100644
index 0000000..1774bdf
--- /dev/null
+++ b/lib/binman.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: Intel
+/*
+ * Access to binman information at runtime
+ *
+ * Copyright 2019 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <binman.h>
+#include <dm.h>
+
+struct binman_info {
+	ofnode image;
+};
+
+static struct binman_info *binman;
+
+int binman_entry_find(const char *name, struct binman_entry *entry)
+{
+	ofnode node;
+	int ret;
+
+	node = ofnode_find_subnode(binman->image, name);
+	if (!ofnode_valid(node))
+		return log_msg_ret("no binman node", -ENOENT);
+
+	ret = ofnode_read_u32(node, "image-pos", &entry->image_pos);
+	if (ret)
+		return log_msg_ret("bad binman node1", ret);
+	ret = ofnode_read_u32(node, "size", &entry->size);
+	if (ret)
+		return log_msg_ret("bad binman node2", ret);
+
+	return 0;
+}
+
+int binman_init(void)
+{
+	binman = malloc(sizeof(struct binman_info));
+	if (!binman)
+		return log_msg_ret("space for binman", -ENOMEM);
+	binman->image = ofnode_path("/binman");
+	if (!ofnode_valid(binman->image))
+		return log_msg_ret("binman node", -EINVAL);
+
+	return 0;
+}