summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2014-08-07 06:15:16 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2014-08-07 06:15:16 +0200
commit5b7b7ee5d943c6b58d9b7f974167d0105ca1b787 (patch)
tree5b01a8a5d8fa8f91f56547761df026adce9dabeb /common
parentf1ee4e8b73a356278056666da8d0c6b5aa53088d (diff)
parent07f93f54521c212558eb09adc812d97dffda443b (diff)
downloadbarebox-5b7b7ee5d943c6b58d9b7f974167d0105ca1b787.tar.gz
barebox-5b7b7ee5d943c6b58d9b7f974167d0105ca1b787.tar.xz
Merge branch 'for-next/metadata'
Conflicts: arch/arm/dts/Makefile common/Makefile lib/Makefile
Diffstat (limited to 'common')
-rw-r--r--common/Kconfig7
-rw-r--r--common/Makefile2
-rw-r--r--common/blspec.c1
-rw-r--r--common/bootm.c1
-rw-r--r--common/hush.c1
-rw-r--r--common/imd-barebox.c25
-rw-r--r--common/imd.c322
-rw-r--r--common/menutree.c1
-rw-r--r--common/uimage.c1
9 files changed, 361 insertions, 0 deletions
diff --git a/common/Kconfig b/common/Kconfig
index 8b361260c0..d3f9801647 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -465,6 +465,13 @@ config BLSPEC
on a device and it allows the Operating System to install / update
kernels.
+config IMD
+ bool "barebox metadata support"
+
+config IMD_TARGET
+ bool "build bareboximd target tool"
+ depends on IMD
+
config KERNEL_INSTALL_TARGET
bool
depends on !SANDBOX
diff --git a/common/Makefile b/common/Makefile
index 4220e15127..ddd7db2578 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -46,6 +46,8 @@ obj-$(CONFIG_UIMAGE) += image.o uimage.o
obj-$(CONFIG_MENUTREE) += menutree.o
obj-$(CONFIG_EFI_GUID) += efi-guid.o
obj-$(CONFIG_EFI_DEVICEPATH) += efi-devicepath.o
+lwl-$(CONFIG_IMD) += imd-barebox.o
+obj-$(CONFIG_IMD) += imd.o
quiet_cmd_pwd_h = PWDH $@
ifdef CONFIG_PASSWORD
diff --git a/common/blspec.c b/common/blspec.c
index 9314eeab04..a4adc48da9 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -21,6 +21,7 @@
#include <malloc.h>
#include <block.h>
#include <fcntl.h>
+#include <libfile.h>
#include <libbb.h>
#include <init.h>
#include <boot.h>
diff --git a/common/bootm.c b/common/bootm.c
index 71390cb845..447c9b624c 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -16,6 +16,7 @@
#include <fs.h>
#include <malloc.h>
#include <memory.h>
+#include <libfile.h>
#include <globalvar.h>
#include <init.h>
diff --git a/common/hush.c b/common/hush.c
index 6be43cf8ea..09d9326c85 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -118,6 +118,7 @@
#include <libbb.h>
#include <glob.h>
#include <getopt.h>
+#include <libfile.h>
#include <libbb.h>
#include <magicvar.h>
#include <linux/list.h>
diff --git a/common/imd-barebox.c b/common/imd-barebox.c
new file mode 100644
index 0000000000..e9cd37d83e
--- /dev/null
+++ b/common/imd-barebox.c
@@ -0,0 +1,25 @@
+#include <common.h>
+#include <image-metadata.h>
+#include <generated/compile.h>
+#include <generated/utsrelease.h>
+
+/*
+ * Mark a imd entry as used so that the linker cannot
+ * throw it away.
+ */
+void imd_used(const void *used)
+{
+}
+
+struct imd_header imd_start_header
+__BAREBOX_IMD_SECTION(.barebox_imd_start) = {
+ .type = cpu_to_le32(IMD_TYPE_START),
+};
+
+struct imd_header imd_end_header
+__BAREBOX_IMD_SECTION(.barebox_imd_end) = {
+ .type = cpu_to_le32(IMD_TYPE_END),
+};
+
+BAREBOX_IMD_TAG_STRING(imd_build_tag, IMD_TYPE_BUILD, UTS_VERSION, 1);
+BAREBOX_IMD_TAG_STRING(imd_release_tag, IMD_TYPE_RELEASE, UTS_RELEASE, 1);
diff --git a/common/imd.c b/common/imd.c
new file mode 100644
index 0000000000..2c837d6f25
--- /dev/null
+++ b/common/imd.c
@@ -0,0 +1,322 @@
+/*
+ * (C) Copyright 2014 Sascha Hauer, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifdef __BAREBOX__
+#include <common.h>
+#include <image-metadata.h>
+#include <libfile.h>
+#include <getopt.h>
+#include <malloc.h>
+#include <fs.h>
+#endif
+
+/*
+ * imd_next - return a pointer to the next metadata field.
+ * @imd The current metadata field
+ */
+struct imd_header *imd_next(struct imd_header *imd)
+{
+ int length;
+
+ length = imd_read_length(imd);
+ length = ALIGN(length, 4);
+ length += 8;
+
+ return (void *)imd + length;
+}
+
+struct imd_header *imd_find_type(struct imd_header *imd, uint32_t type)
+{
+ imd_for_each(imd, imd)
+ if (imd_read_type(imd) == type)
+ return imd;
+
+ return NULL;
+}
+
+static int imd_next_validate(void *buf, int bufsize, int start_ofs)
+{
+ int length, size;
+ struct imd_header *imd = buf + start_ofs;
+
+ size = bufsize - start_ofs;
+
+ if (size < 8) {
+ debug("trunkated tag at offset %dd\n", start_ofs);
+ return -EINVAL;
+ }
+
+ length = imd_read_length(imd);
+ length = ALIGN(length, 4);
+ length += 8;
+
+ if (size < length) {
+ debug("tag at offset %d with size %d exceeds bufsize %d\n",
+ start_ofs, size, bufsize);
+ return -EINVAL;
+ }
+
+ debug("tag at offset %d has length %d\n", start_ofs, length);
+
+ return length;
+}
+
+static int imd_validate_tags(void *buf, int bufsize, int start_ofs)
+{
+ int ret;
+ struct imd_header *imd = buf + start_ofs;
+
+ while (1) {
+ uint32_t type;
+
+ ret = imd_next_validate(buf, bufsize, start_ofs);
+ if (ret < 0) {
+ debug("Invalid tag at offset %d\n", start_ofs);
+ return -EINVAL;
+ }
+
+ imd = (void *)imd + ret;
+ start_ofs += ret;
+
+ type = imd_read_type(imd);
+
+ if (!imd_type_valid(type)) {
+ debug("Invalid: tag: 0x%08x\n", type);
+ return -EINVAL;
+ }
+
+ if (type == IMD_TYPE_END)
+ return 0;
+ }
+}
+
+/*
+ * imd_search_validate - find valid metadata in a buffer
+ * @buf the buffer
+ * @size buffer size
+ * @start The returned pointer to the metadata
+ *
+ * This iterates over a buffer and searches for metadata. The metadata
+ * is checked for consistency (length fields not exceeding buffer and
+ * presence of end header) and returned in @start. The returned pointer
+ * is only valid when 0 is returned. The returned data may be unaligned.
+ */
+static int imd_search_validate(void *buf, int size, struct imd_header **start)
+{
+ int start_ofs = 0;
+ int i, ret;
+
+ for (i = start_ofs; i < size - 32; i++) {
+ uint32_t type;
+
+ type = imd_read_le32(buf + i);
+
+ if (type != IMD_TYPE_START)
+ continue;
+
+ debug("Start tag found at offset %d\n", i);
+
+ ret = imd_validate_tags(buf, size, i);
+ if (!ret) {
+ *start = buf + i;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+struct imd_type_names {
+ uint32_t type;
+ const char *name;
+};
+
+static struct imd_type_names imd_types[] = {
+ {
+ .type = IMD_TYPE_RELEASE,
+ .name = "release",
+ }, {
+ .type = IMD_TYPE_BUILD,
+ .name = "build",
+ }, {
+ .type = IMD_TYPE_MODEL,
+ .name = "model",
+ }, {
+ .type = IMD_TYPE_PARAMETER,
+ .name = "parameter",
+ }, {
+ .type = IMD_TYPE_OF_COMPATIBLE,
+ .name = "of_compatible",
+ },
+};
+
+static const char *imd_type_to_name(uint32_t type)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(imd_types); i++)
+ if (imd_types[i].type == type)
+ return imd_types[i].name;
+
+ return "unknown";
+}
+
+static uint32_t imd_name_to_type(const char *name)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(imd_types); i++)
+ if (!strcmp(imd_types[i].name, name))
+ return imd_types[i].type;
+
+ return IMD_TYPE_INVALID;
+}
+
+static char *imd_string_data(struct imd_entry_string *imd_string, int index)
+{
+ int i, total = 0, l = 0;
+ int len = imd_read_length(&imd_string->header);
+ char *p = imd_string->data;
+
+ for (i = 0; total < len; total += l, p += l) {
+ l = strlen(p) + 1;
+ if (i++ == index)
+ return p;
+ }
+
+ return NULL;
+}
+
+static char *imd_concat_strings(struct imd_entry_string *imd_string)
+{
+ int i, len = imd_read_length(&imd_string->header);
+ char *str;
+
+ str = malloc(len);
+ if (!str)
+ return NULL;
+
+ memcpy(str, imd_string->data, len);
+
+ for (i = 0; i < len - 1; i++)
+ if (str[i] == 0)
+ str[i] = ' ';
+
+ return str;
+}
+
+int imd_command_verbose;
+
+int imd_command(int argc, char *argv[])
+{
+ int ret, opt, strno = -1;
+ void *buf;
+ size_t size;
+ uint32_t type = IMD_TYPE_INVALID;
+ struct imd_header *imd_start, *imd;
+ const char *filename;
+ const char *variable_name = NULL;
+ char *str;
+
+ imd_command_verbose = 0;
+
+ while ((opt = getopt(argc, argv, "vt:s:n:")) > 0) {
+ switch(opt) {
+ case 't':
+ type = imd_name_to_type(optarg);
+ if (type == IMD_TYPE_INVALID) {
+ fprintf(stderr, "no such type: %s\n", optarg);
+ return -ENOSYS;
+ }
+ break;
+ case 's':
+ variable_name = optarg;
+ break;
+ case 'v':
+ imd_command_verbose = 1;
+ break;
+ case 'n':
+ strno = simple_strtoul(optarg, NULL, 0);
+ break;
+ default:
+ return -ENOSYS;
+ }
+ }
+
+ if (optind == argc) {
+ fprintf(stderr, "No image given\n");
+ return -ENOSYS;
+ }
+
+ filename = argv[optind];
+
+ ret = read_file_2(filename, &size, &buf, 0x100000);
+ if (ret && ret != -EFBIG)
+ return -errno;
+
+ ret = imd_search_validate(buf, size, &imd_start);
+ if (ret)
+ return ret;
+
+ if (type == IMD_TYPE_INVALID) {
+ imd_for_each(imd_start, imd) {
+ uint32_t type = imd_read_type(imd);
+
+ if (imd_is_string(type)) {
+ struct imd_entry_string *imd_string =
+ (struct imd_entry_string *)imd;
+
+ str = imd_concat_strings(imd_string);
+
+ printf("%s: %s\n", imd_type_to_name(type), str);
+ } else {
+ debug("Unknown tag 0x%08x\n", type);
+ }
+ }
+ } else {
+ imd = imd_find_type(imd_start, type);
+ if (!imd) {
+ debug("No tag of type 0x%08x found\n", type);
+ return -ENODATA;
+ }
+
+ if (imd_is_string(type)) {
+ struct imd_entry_string *imd_string =
+ (struct imd_entry_string *)imd;
+
+ if (strno >= 0)
+ str = imd_string_data(imd_string, strno);
+ else
+ str = imd_concat_strings(imd_string);
+
+ if (!str)
+ return -ENODATA;
+
+ if (variable_name)
+ imd_command_setenv(variable_name, str);
+ else
+ printf("%s\n", str);
+
+ if (strno < 0)
+ free(str);
+ } else {
+ printf("tag 0x%08x present\n", type);
+ }
+ }
+
+ return 0;
+}
diff --git a/common/menutree.c b/common/menutree.c
index 814512d7b7..97e628de88 100644
--- a/common/menutree.c
+++ b/common/menutree.c
@@ -15,6 +15,7 @@
#include <glob.h>
#include <menu.h>
#include <fs.h>
+#include <libfile.h>
#include <linux/stat.h>
diff --git a/common/uimage.c b/common/uimage.c
index 4ef09682c1..a7011a7623 100644
--- a/common/uimage.c
+++ b/common/uimage.c
@@ -22,6 +22,7 @@
#include <malloc.h>
#include <errno.h>
#include <libbb.h>
+#include <libfile.h>
#include <uncompress.h>
#include <fcntl.h>
#include <fs.h>