From: Sascha Hauer <s.hauer@pengutronix.de>
To: Barebox List <barebox@lists.infradead.org>
Subject: [PATCH 13/14] bootm: add initial FIT support
Date: Fri, 22 Jan 2016 08:32:31 +0100 [thread overview]
Message-ID: <1453447952-30818-14-git-send-email-s.hauer@pengutronix.de> (raw)
In-Reply-To: <1453447952-30818-1-git-send-email-s.hauer@pengutronix.de>
From: Jan Luebbe <jlu@pengutronix.de>
This implementation is inspired by U-Boot's FIT support. Instead of
using libfdt (which does not exist in barebox), configuration signatures
are verified by using a simplified DT parser based on barebox's own
code.
Currently, only signed configurations with hashed images are supported,
as the other variants are less useful for verified boot. Compatible FIT
images can be created using U-Boot's mkimage tool.
Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/lib/bootm.c | 8 +
commands/Kconfig | 25 +++
common/Kconfig | 9 +
common/Makefile | 1 +
common/bootm.c | 53 ++++-
common/image-fit.c | 584 +++++++++++++++++++++++++++++++++++++++++++++++++++
include/boot.h | 4 +
include/image-fit.h | 45 ++++
8 files changed, 726 insertions(+), 3 deletions(-)
create mode 100644 common/image-fit.c
create mode 100644 include/image-fit.h
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 4dfe148..1913d5f 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -531,6 +531,12 @@ BAREBOX_MAGICVAR(aimage_noverwrite_bootargs, "Disable overwrite of the bootargs
BAREBOX_MAGICVAR(aimage_noverwrite_tags, "Disable overwrite of the tags addr with the one present in aimage");
#endif
+static struct image_handler arm_fit_handler = {
+ .name = "FIT image",
+ .bootm = do_bootm_linux,
+ .filetype = filetype_oftree,
+};
+
static struct binfmt_hook binfmt_aimage_hook = {
.type = filetype_aimage,
.exec = "bootm",
@@ -556,6 +562,8 @@ static int armlinux_register_image_handler(void)
register_image_handler(&aimage_handler);
binfmt_register(&binfmt_aimage_hook);
}
+ if (IS_BUILTIN(CONFIG_CMD_BOOTM_FITIMAGE))
+ register_image_handler(&arm_fit_handler);
binfmt_register(&binfmt_arm_zimage_hook);
binfmt_register(&binfmt_barebox_hook);
diff --git a/commands/Kconfig b/commands/Kconfig
index 1743670..b4fdc86 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -418,6 +418,31 @@ config CMD_BOOTM_AIMAGE
help
Support using Android Images.
+config CMD_BOOTM_FITIMAGE
+ bool
+ prompt "FIT image support"
+ select FITIMAGE
+ depends on CMD_BOOTM && ARM
+ help
+ Support using Flattened Image Tree (FIT) Images. FIT is an image
+ format introduced by U-Boot. A FIT image contains one or multiple
+ kernels, device trees and initrds. The FIT image itself is a flattened
+ device tree binary. Have a look at the u-boot source tree
+ in the "doc/uImage.FIT" folder for more information:
+ http://git.denx.de/?p=u-boot.git;a=tree;f=doc/uImage.FIT
+
+config CMD_BOOTM_FITIMAGE_SIGNATURE
+ bool
+ prompt "support verifying signed FIT images"
+ depends on CMD_BOOTM_FITIMAGE
+ select FITIMAGE_SIGNATURE
+ help
+ Support verifying signed FIT images. This requires FIT images
+ as described in:
+ http://git.denx.de/?p=u-boot.git;a=blob;f=doc/uImage.FIT/signature.txt
+ Additionally the barebox device tree needs a /signature node with the
+ public key with which the image has been signed.
+
config CMD_BOOTU
tristate
default y
diff --git a/common/Kconfig b/common/Kconfig
index 8e79509..345de50 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -66,6 +66,15 @@ config UIMAGE
select CRC32
bool
+config FITIMAGE
+ bool
+ select OFTREE
+ select DIGEST
+
+config FITIMAGE_SIGNATURE
+ select CRYPTO_RSA
+ bool
+
config LOGBUF
bool
diff --git a/common/Makefile b/common/Makefile
index 56e6bec..ffaf8e7 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_SHELL_HUSH) += hush.o
obj-$(CONFIG_SHELL_SIMPLE) += parser.o
obj-$(CONFIG_STATE) += state.o
obj-$(CONFIG_UIMAGE) += image.o uimage.o
+obj-$(CONFIG_FITIMAGE) += image-fit.o
obj-$(CONFIG_MENUTREE) += menutree.o
obj-$(CONFIG_EFI_GUID) += efi-guid.o
obj-$(CONFIG_EFI_DEVICEPATH) += efi-devicepath.o
diff --git a/common/bootm.c b/common/bootm.c
index 78a6bb5..d8acff8 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -17,6 +17,7 @@
#include <malloc.h>
#include <memory.h>
#include <libfile.h>
+#include <image-fit.h>
#include <globalvar.h>
#include <init.h>
#include <linux/stat.h>
@@ -92,6 +93,17 @@ int bootm_load_os(struct image_data *data, unsigned long load_address)
if (load_address == UIMAGE_INVALID_ADDRESS)
return -EINVAL;
+ if (data->os_fit) {
+ data->os_res = request_sdram_region("kernel",
+ load_address,
+ data->os_fit->kernel_size);
+ if (!data->os_res)
+ return -ENOMEM;
+ memcpy((void *)load_address, data->os_fit->kernel,
+ data->os_fit->kernel_size);
+ return 0;
+ }
+
if (data->os) {
int num;
@@ -121,6 +133,9 @@ bool bootm_has_initrd(struct image_data *data)
if (!IS_ENABLED(CONFIG_CMD_BOOTM_INITRD))
return false;
+ if (data->os_fit && data->os_fit->initrd)
+ return true;
+
if (data->initrd_file)
return true;
@@ -178,6 +193,18 @@ int bootm_load_initrd(struct image_data *data, unsigned long load_address)
if (data->initrd_res)
return 0;
+ if (data->os_fit && data->os_fit->initrd) {
+ data->initrd_res = request_sdram_region("initrd",
+ load_address,
+ data->os_fit->initrd_size);
+ if (!data->initrd_res)
+ return -ENOMEM;
+ memcpy((void *)load_address, data->os_fit->initrd,
+ data->os_fit->initrd_size);
+ printf("Loaded initrd from FIT image\n");
+ goto done1;
+ }
+
type = file_name_detect_type(data->initrd_file);
if ((int)type < 0) {
@@ -216,7 +243,7 @@ done:
if (type == filetype_uimage && data->initrd->header.ih_type == IH_TYPE_MULTI)
printf(", multifile image %s", data->initrd_part);
printf("\n");
-
+done1:
printf("initrd is at " PRINTF_CONVERSION_RESOURCE "-" PRINTF_CONVERSION_RESOURCE "\n",
data->initrd_res->start,
data->initrd_res->end);
@@ -289,7 +316,9 @@ int bootm_load_devicetree(struct image_data *data, unsigned long load_address)
if (!IS_ENABLED(CONFIG_OFTREE))
return 0;
- if (data->oftree_file) {
+ if (data->os_fit && data->os_fit->oftree) {
+ data->of_root_node = of_unflatten_dtb(data->os_fit->oftree);
+ } else if (data->oftree_file) {
size_t size;
type = file_name_detect_type(data->oftree_file);
@@ -376,6 +405,8 @@ int bootm_get_os_size(struct image_data *data)
if (data->os)
return uimage_get_size(data->os,
simple_strtoul(data->os_part, NULL, 0));
+ if (data->os_fit)
+ return data->os_fit->kernel_size;
if (data->os_file) {
struct stat s;
@@ -495,10 +526,24 @@ int bootm_boot(struct bootm_data *bootm_data)
goto err_out;
}
+ if (IS_ENABLED(CONFIG_FITIMAGE) && os_type == filetype_oftree) {
+ struct fit_handle *fit;
+
+ fit = fit_open(data->os_file, data->os_part, data->verbose, data->verify);
+ if (IS_ERR(fit)) {
+ printf("Loading FIT image %s failed with: %s\n", data->os_file,
+ strerrorp(fit));
+ ret = PTR_ERR(fit);
+ goto err_out;
+ }
+
+ data->os_fit = fit;
+ }
+
if (os_type == filetype_uimage) {
ret = bootm_open_os_uimage(data);
if (ret) {
- printf("Loading OS image failed with %s\n",
+ printf("Loading OS image failed with: %s\n",
strerror(-ret));
goto err_out;
}
@@ -544,6 +589,8 @@ err_out:
uimage_close(data->initrd);
if (data->os)
uimage_close(data->os);
+ if (IS_ENABLED(CONFIG_FITIMAGE) && data->os_fit)
+ fit_close(data->os_fit);
if (data->of_root_node && data->of_root_node != of_get_root_node())
of_delete_node(data->of_root_node);
diff --git a/common/image-fit.c b/common/image-fit.c
new file mode 100644
index 0000000..4f5c1f1
--- /dev/null
+++ b/common/image-fit.c
@@ -0,0 +1,584 @@
+/*
+ * Copyright (C) Jan Lübbe, 2014
+ *
+ * This code is inspired by the U-Boot FIT image code.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define pr_fmt(fmt) "FIT: " fmt
+#include <common.h>
+#include <init.h>
+#include <boot.h>
+#include <libfile.h>
+#include <fdt.h>
+#include <digest.h>
+#include <of.h>
+#include <fs.h>
+#include <malloc.h>
+#include <linux/ctype.h>
+#include <asm/byteorder.h>
+#include <errno.h>
+#include <linux/err.h>
+#include <stringlist.h>
+#include <rsa.h>
+#include <image-fit.h>
+
+#define FDT_MAX_DEPTH 32
+#define FDT_MAX_PATH_LEN 200
+
+#define CHECK_LEVEL_NONE 0
+#define CHECK_LEVEL_HASH 1
+#define CHECK_LEVEL_SIG 2
+#define CHECK_LEVEL_MAX 3
+
+static uint32_t dt_struct_advance(struct fdt_header *f, uint32_t dt, int size)
+{
+ dt += size;
+ dt = ALIGN(dt, 4);
+
+ if (dt > f->off_dt_struct + f->size_dt_struct)
+ return 0;
+
+ return dt;
+}
+
+static char *dt_string(struct fdt_header *f, char *strstart, uint32_t ofs)
+{
+ if (ofs > f->size_dt_strings)
+ return NULL;
+ else
+ return strstart + ofs;
+}
+
+static int of_read_string_list(struct device_node *np, const char *name, struct string_list *sl)
+{
+ struct property *prop;
+ const char *s;
+
+ of_property_for_each_string(np, name, prop, s) {
+ string_list_add(sl, s);
+ }
+
+ return prop ? 0 : -EINVAL;
+}
+
+static int fit_digest(void *fit, struct digest *digest,
+ struct string_list *inc_nodes, struct string_list *exc_props,
+ uint32_t hashed_strings_start, uint32_t hashed_strings_size)
+{
+ struct fdt_header *fdt = fit;
+ uint32_t dt_struct;
+ void *dt_strings;
+ struct fdt_header f = {};
+ int stack[FDT_MAX_DEPTH];
+ char path[FDT_MAX_PATH_LEN];
+ char *end;
+ uint32_t tag;
+ int start = -1;
+ int depth = -1;
+ int want = 0;
+
+ f.totalsize = fdt32_to_cpu(fdt->totalsize);
+ f.off_dt_struct = fdt32_to_cpu(fdt->off_dt_struct);
+ f.size_dt_struct = fdt32_to_cpu(fdt->size_dt_struct);
+ f.off_dt_strings = fdt32_to_cpu(fdt->off_dt_strings);
+ f.size_dt_strings = fdt32_to_cpu(fdt->size_dt_strings);
+
+ if (hashed_strings_start > f.size_dt_strings ||
+ hashed_strings_size > f.size_dt_strings ||
+ hashed_strings_start + hashed_strings_size > f.size_dt_strings) {
+ pr_err("%s: hashed-strings too large\n", __func__);
+ return -EINVAL;
+ }
+
+ dt_struct = f.off_dt_struct;
+ dt_strings = (void *)fdt + f.off_dt_strings;
+
+ end = path;
+ *end = '\0';
+
+ do {
+ const struct fdt_property *fdt_prop;
+ const struct fdt_node_header *fnh;
+ const char *name;
+ int include = 0;
+ int stop_at = 0;
+ int offset = dt_struct;
+ int maxlen, len;
+
+ tag = be32_to_cpu(*(uint32_t *)(fit + dt_struct));
+
+ switch (tag) {
+ case FDT_BEGIN_NODE:
+ fnh = fit + dt_struct;
+ name = fnh->name;
+ maxlen = (unsigned long)fdt + f.off_dt_struct +
+ f.size_dt_struct - (unsigned long)name;
+
+ len = strnlen(name, maxlen + 1);
+ if (len > maxlen)
+ return -ESPIPE;
+
+ dt_struct = dt_struct_advance(&f, dt_struct,
+ sizeof(struct fdt_node_header) + len + 1);
+
+ depth++;
+ if (depth == FDT_MAX_DEPTH)
+ return -ESPIPE;
+ if (end - path + 2 + len >= FDT_MAX_PATH_LEN)
+ return -ESPIPE;
+ if (end != path + 1)
+ *end++ = '/';
+ strcpy(end, name);
+ end += len;
+ stack[depth] = want;
+ if (want == 1)
+ stop_at = offset;
+ if (string_list_contains(inc_nodes, path))
+ want = 2;
+ else if (want)
+ want--;
+ else
+ stop_at = offset;
+ include = want;
+
+ break;
+
+ case FDT_END_NODE:
+ dt_struct = dt_struct_advance(&f, dt_struct, FDT_TAGSIZE);
+
+ include = want;
+ want = stack[depth--];
+ while (end > path && *--end != '/')
+ ;
+ *end = '\0';
+
+ break;
+
+ case FDT_PROP:
+ fdt_prop = fit + dt_struct;
+ len = fdt32_to_cpu(fdt_prop->len);
+
+ name = dt_string(&f, dt_strings, fdt32_to_cpu(fdt_prop->nameoff));
+ if (!name)
+ return -ESPIPE;
+
+ dt_struct = dt_struct_advance(&f, dt_struct,
+ sizeof(struct fdt_property) + len);
+
+ include = want >= 2;
+ stop_at = offset;
+ if (string_list_contains(exc_props, name))
+ include = 0;
+
+ break;
+
+ case FDT_NOP:
+ dt_struct = dt_struct_advance(&f, dt_struct, FDT_TAGSIZE);
+
+ include = want >= 2;
+ stop_at = offset;
+
+ break;
+
+ case FDT_END:
+ dt_struct = dt_struct_advance(&f, dt_struct, FDT_TAGSIZE);
+
+ include = 1;
+
+ break;
+
+ default:
+ pr_err("%s: Unknown tag 0x%08X\n", __func__, tag);
+ return -EINVAL;
+ }
+
+ if (!dt_struct)
+ return -ESPIPE;
+
+ pr_debug("%s: include %d, want %d, offset 0x%x, len 0x%x\n",
+ path, include, want, offset, dt_struct-offset);
+
+ if (include && start == -1)
+ start = offset;
+
+ if (!include && start != -1) {
+ pr_debug("region: 0x%p+0x%x\n", fit + start, offset - start);
+ digest_update(digest, fit + start, offset - start);
+ start = -1;
+ }
+ } while (tag != FDT_END);
+
+ pr_debug("region: 0x%p+0x%x\n", fit + start, dt_struct - start);
+ digest_update(digest, fit + start, dt_struct - start);
+
+ pr_debug("strings: 0x%p+0x%x\n", dt_strings+hashed_strings_start, hashed_strings_size);
+ digest_update(digest, dt_strings + hashed_strings_start, hashed_strings_size);
+
+ return 0;
+}
+
+/*
+ * The consistency of the FTD structure was already checked by of_unflatten_dtb()
+ */
+static int fit_verify_signature(struct device_node *sig_node, void *fit)
+{
+ uint32_t hashed_strings_start, hashed_strings_size;
+ struct string_list inc_nodes, exc_props;
+ struct rsa_public_key key = {};
+ struct digest *digest;
+ int sig_len;
+ const char *algo_name, *key_name, *sig_value;
+ char *key_path;
+ struct device_node *key_node;
+ enum hash_algo algo;
+ void *hash;
+ int ret;
+
+ if (of_property_read_string(sig_node, "algo", &algo_name)) {
+ pr_err("algo not found\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ if (strcmp(algo_name, "sha1,rsa2048") == 0) {
+ algo = HASH_ALGO_SHA1;
+ } else if (strcmp(algo_name, "sha256,rsa4096") == 0) {
+ algo = HASH_ALGO_SHA256;
+ } else {
+ pr_err("unknown algo %s\n", algo_name);
+ ret = -EINVAL;
+ goto out;
+ }
+ digest = digest_alloc_by_algo(algo);
+ if (!digest) {
+ pr_err("unsupported algo %s\n", algo_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ sig_value = of_get_property(sig_node, "value", &sig_len);
+ if (!sig_value) {
+ pr_err("signature value not found in %s\n", sig_node->full_name);
+ ret = -EINVAL;
+ goto out_free_digest;
+ }
+
+ if (of_property_read_string(sig_node, "key-name-hint", &key_name)) {
+ pr_err("key name not found in %s\n", sig_node->full_name);
+ ret = -EINVAL;
+ goto out_free_digest;
+ }
+ key_path = xasprintf("/signature/key-%s", key_name);
+ key_node = of_find_node_by_path(key_path);
+ free(key_path);
+ if (!key_node) {
+ pr_info("failed to find key node\n");
+ ret = -ENOENT;
+ goto out_free_digest;
+ }
+
+ ret = rsa_of_read_key(key_node, &key);
+ if (ret) {
+ pr_info("failed to read key in %s\n", key_node->full_name);
+ ret = -ENOENT;
+ goto out_free_digest;
+ }
+
+ if (of_property_read_u32_index(sig_node, "hashed-strings", 0, &hashed_strings_start)) {
+ pr_err("hashed-strings start not found in %s\n", sig_node->full_name);
+ ret = -EINVAL;
+ goto out_free_digest;
+ }
+ if (of_property_read_u32_index(sig_node, "hashed-strings", 1, &hashed_strings_size)) {
+ pr_err("hashed-strings size not found in %s\n", sig_node->full_name);
+ ret = -EINVAL;
+ goto out_free_digest;
+ }
+
+ string_list_init(&inc_nodes);
+ string_list_init(&exc_props);
+
+ if (of_read_string_list(sig_node, "hashed-nodes", &inc_nodes)) {
+ pr_err("hashed-nodes property not found in %s\n", sig_node->full_name);
+ ret = -EINVAL;
+ goto out_sl;
+ }
+
+ string_list_add(&exc_props, "data");
+
+ digest_init(digest);
+ ret = fit_digest(fit, digest, &inc_nodes, &exc_props, hashed_strings_start, hashed_strings_size);
+ hash = xzalloc(digest_length(digest));
+ digest_final(digest, hash);
+
+ ret = rsa_verify(&key, sig_value, sig_len, hash, algo);
+ if (ret) {
+ pr_info("image signature BAD\n");
+ ret = -EBADMSG;
+ } else {
+ pr_info("image signature OK\n");
+ ret = 0;
+ }
+
+ free(hash);
+ out_sl:
+ string_list_free(&inc_nodes);
+ string_list_free(&exc_props);
+ out_free_digest:
+ digest_free(digest);
+ out:
+ return ret;
+}
+
+static int fit_verify_hash(struct device_node *hash, const void *data, int data_len)
+{
+ struct digest *d;
+ const char *algo;
+ const char *value_read;
+ char *value_calc;
+ int hash_len, ret;
+
+ value_read = of_get_property(hash, "value", &hash_len);
+ if (!value_read) {
+ pr_err("%s: \"value\" property not found\n", hash->full_name);
+ return -EINVAL;
+ }
+
+ if (of_property_read_string(hash, "algo", &algo)) {
+ pr_err("%s: \"algo\" property not found\n", hash->full_name);
+ return -EINVAL;
+ }
+
+ d = digest_alloc(algo);
+ if (!d) {
+ pr_err("%s: unsupported algo %s\n", hash->full_name, algo);
+ return -EINVAL;
+ }
+
+ if (hash_len != digest_length(d)) {
+ pr_err("%s: invalid hash length %d\n", hash->full_name, hash_len);
+ ret = -EINVAL;
+ goto err_digest_free;
+ }
+
+ value_calc = xmalloc(hash_len);
+
+ digest_init(d);
+ digest_update(d, data, data_len);
+ digest_final(d, value_calc);
+
+ if (memcmp(value_read, value_calc, hash_len)) {
+ pr_info("%s: hash BAD\n", hash->full_name);
+ ret = -EBADMSG;
+ } else {
+ pr_info("%s: hash OK\n", hash->full_name);
+ ret = 0;
+ }
+
+ free(value_calc);
+
+err_digest_free:
+ digest_free(d);
+
+ return ret;
+}
+
+static int fit_open_image(struct fit_handle *handle, const char *unit, const void **outdata,
+ unsigned long *outsize)
+{
+ struct device_node *image = NULL, *hash;
+ const char *type = NULL, *desc= "(no description)";
+ const void *data;
+ int data_len;
+ int ret = 0;
+
+ image = of_get_child_by_name(handle->root, "images");
+ if (!image)
+ return -ENOENT;
+
+ image = of_get_child_by_name(image, unit);
+ if (!image)
+ return -ENOENT;
+
+ of_property_read_string(image, "description", &desc);
+ pr_info("image '%s': '%s'\n", unit, desc);
+
+ of_property_read_string(image, "type", &type);
+ if (!type) {
+ pr_err("No \"type\" property found in %s\n", image->full_name);
+ return -EINVAL;
+ }
+
+ data = of_get_property(image, "data", &data_len);
+ if (!data) {
+ pr_err("data not found\n");
+ return -EINVAL;
+ }
+
+ if (handle->verify > BOOTM_VERIFY_NONE) {
+ ret = -EINVAL;
+ for_each_child_of_node(image, hash) {
+ if (handle->verbose)
+ of_print_nodes(hash, 0);
+ ret = fit_verify_hash(hash, data, data_len);
+ if (ret < 0)
+ return ret;
+ }
+ }
+ if (ret < 0)
+ return ret;
+
+ *outdata = data;
+ *outsize = data_len;
+
+ return 0;
+}
+
+static int fit_open_configuration(struct fit_handle *handle, const char *name)
+{
+ struct device_node *conf_node = NULL, *sig_node;
+ const char *unit, *desc = "(no description)";
+ int ret;
+
+ conf_node = of_get_child_by_name(handle->root, "configurations");
+ if (!conf_node)
+ return -ENOENT;
+
+ if (name) {
+ unit = name;
+ } else if (of_property_read_string(conf_node, "default", &unit)) {
+ unit = "conf@1";
+ }
+
+ conf_node = of_get_child_by_name(conf_node, unit);
+ if (!conf_node) {
+ pr_err("configuration '%s' not found\n", unit);
+ return -ENOENT;
+ }
+
+ of_property_read_string(conf_node, "description", &desc);
+ pr_info("configuration '%s': %s\n", unit, desc);
+
+ if (IS_ENABLED(CONFIG_FITIMAGE_SIGNATURE) &&
+ handle->verify == BOOTM_VERIFY_SIGNATURE) {
+ ret = -EINVAL;
+ for_each_child_of_node(conf_node, sig_node) {
+ if (handle->verbose)
+ of_print_nodes(sig_node, 0);
+ ret = fit_verify_signature(sig_node, handle->fit);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (ret < 0)
+ return ret;
+ }
+
+ if (of_property_read_string(conf_node, "kernel", &unit) == 0) {
+ ret = fit_open_image(handle, unit, &handle->kernel, &handle->kernel_size);
+ if (ret)
+ return ret;
+ } else {
+ return -ENOENT;
+ }
+
+ if (of_property_read_string(conf_node, "fdt", &unit) == 0) {
+ ret = fit_open_image(handle, unit, &handle->oftree, &handle->oftree_size);
+ if (ret)
+ return ret;
+ }
+
+ if (of_property_read_string(conf_node, "ramdisk", &unit) == 0) {
+ ret = fit_open_image(handle, unit, &handle->initrd, &handle->initrd_size);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+struct fit_handle *fit_open(const char *filename, const char *config, bool verbose,
+ enum bootm_verify verify)
+{
+ struct fit_handle *handle = NULL;
+ const char *desc = "(no description)";
+ int ret;
+
+ handle = xzalloc(sizeof(struct fit_handle));
+
+ handle->verbose = verbose;
+
+ ret = read_file_2(filename, &handle->size, &handle->fit, FILESIZE_MAX);
+ if (ret) {
+ pr_err("unable to read %s: %s\n", filename, strerror(-ret));
+ goto err;
+ }
+
+ handle->root = of_unflatten_dtb(handle->fit);
+ if (IS_ERR(handle->root)) {
+ ret = PTR_ERR(handle->root);
+ goto err;
+ }
+
+ handle->verify = verify;
+
+ of_property_read_string(handle->root, "description", &desc);
+ pr_info("'%s': %s\n", filename, desc);
+
+ ret = fit_open_configuration(handle, config);
+ if (ret)
+ goto err;
+
+ return handle;
+ err:
+ if (handle->root)
+ of_delete_node(handle->root);
+ free(handle->fit);
+ free(handle);
+
+ return ERR_PTR(ret);
+}
+
+void fit_close(struct fit_handle *handle)
+{
+ if (handle->root)
+ of_delete_node(handle->root);
+ if (handle->fit)
+ free(handle->fit);
+ free(handle);
+}
+
+#ifdef CONFIG_SANDBOX
+static int do_bootm_sandbox_fit(struct image_data *data)
+{
+ struct fit_handle *handle;
+ handle = fit_open(data->os_file, data->os_part, data->verbose);
+ if (handle)
+ fit_close(handle);
+ return 0;
+}
+
+static struct image_handler sandbox_fit_handler = {
+ .name = "FIT image",
+ .bootm = do_bootm_sandbox_fit,
+ .filetype = filetype_oftree,
+};
+
+static int sandbox_fit_register(void)
+{
+ return register_image_handler(&sandbox_fit_handler);
+}
+late_initcall(sandbox_fit_register);
+#endif
diff --git a/include/boot.h b/include/boot.h
index 363a02a..0198cc8 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -34,6 +34,10 @@ struct image_data {
/* if os is an uImage this will be provided */
struct uimage_handle *os;
+
+ /* if os is a FIT image this will be provided */
+ struct fit_handle *os_fit;
+
char *os_part;
/* otherwise only the filename will be provided */
diff --git a/include/image-fit.h b/include/image-fit.h
new file mode 100644
index 0000000..c9d6911
--- /dev/null
+++ b/include/image-fit.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) Jan Lübbe, 2014
+ */
+
+#ifndef __IMAGE_FIT_H__
+#define __IMAGE_FIT_H__
+
+#include <linux/types.h>
+#include <boot.h>
+
+struct fit_handle {
+ void *fit;
+ size_t size;
+
+ bool verbose;
+ enum bootm_verify verify;
+
+ struct device_node *root;
+
+ const void *kernel;
+ unsigned long kernel_size;
+ const void *oftree;
+ unsigned long oftree_size;
+ const void *initrd;
+ unsigned long initrd_size;
+};
+
+struct fit_handle *fit_open(const char *filename, const char *config, bool verbose,
+ enum bootm_verify verify);
+void fit_close(struct fit_handle *handle);
+
+#endif /* __IMAGE_FIT_H__ */
--
2.7.0.rc3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2016-01-22 7:33 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-22 7:32 [PATCH v4] " Sascha Hauer
2016-01-22 7:32 ` [PATCH 01/14] ARM: zImage: add missing free() in appended device tree code Sascha Hauer
2016-01-22 7:32 ` [PATCH 02/14] bootm: Do not call uimage_close twice Sascha Hauer
2016-01-22 7:32 ` [PATCH 03/14] bootm: introduce bootm_get_os_size Sascha Hauer
2016-01-22 7:32 ` [PATCH 04/14] bootm: use names instead of numbers for image parts Sascha Hauer
2016-01-22 7:32 ` [PATCH 05/14] ARM: bootm: Use kernel handler to start barebox image Sascha Hauer
2016-01-22 7:32 ` [PATCH 06/14] bootm: Push dryrun to handlers Sascha Hauer
2016-01-22 7:32 ` [PATCH 07/14] bootm: move initrd code together Sascha Hauer
2016-01-22 7:32 ` [PATCH 08/14] bootm: move oftree " Sascha Hauer
2016-01-22 7:32 ` [PATCH 09/14] bootm: Initialize bootm_data defaults in single place Sascha Hauer
2016-01-22 7:32 ` [PATCH 10/14] crypto: add digest_alloc_by_algo() Sascha Hauer
2016-01-22 7:32 ` [PATCH 11/14] crypto: add RSA support Sascha Hauer
2016-01-22 7:32 ` [PATCH 12/14] bootm: make verifying/hashing configurable Sascha Hauer
2016-01-22 7:32 ` Sascha Hauer [this message]
2016-01-22 7:32 ` [PATCH 14/14] bootm: Add option to force booting signed images Sascha Hauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1453447952-30818-14-git-send-email-s.hauer@pengutronix.de \
--to=s.hauer@pengutronix.de \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox