summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/image-fit.c32
-rw-r--r--drivers/of/base.c4
-rw-r--r--include/of.h8
-rw-r--r--include/uncompress.h6
-rw-r--r--lib/uncompress.c40
5 files changed, 87 insertions, 3 deletions
diff --git a/common/image-fit.c b/common/image-fit.c
index 507a857cad..3e6e7fbd6d 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -21,6 +21,7 @@
#include <linux/err.h>
#include <stringlist.h>
#include <rsa.h>
+#include <uncompress.h>
#include <image-fit.h>
#define FDT_MAX_DEPTH 32
@@ -559,6 +560,11 @@ int fit_get_image_address(struct fit_handle *handle, void *configuration,
return ret;
}
+static void fit_uncompress_error_fn(char *x)
+{
+ pr_err("%s\n", x);
+}
+
/**
* fit_open_image - Open an image in a FIT image
* @handle: The FIT image handle
@@ -581,7 +587,8 @@ int fit_open_image(struct fit_handle *handle, void *configuration,
unsigned long *outsize)
{
struct device_node *image;
- const char *unit = name, *type = NULL, *desc= "(no description)";
+ const char *unit = name, *type = NULL, *compression = NULL,
+ *desc= "(no description)";
const void *data;
int data_len;
int ret = 0;
@@ -613,6 +620,29 @@ int fit_open_image(struct fit_handle *handle, void *configuration,
if (ret < 0)
return ret;
+ of_property_read_string(image, "compression", &compression);
+ if (compression && strcmp(compression, "none") != 0) {
+ void *uc_data;
+
+ if (!IS_ENABLED(CONFIG_UNCOMPRESS)) {
+ pr_err("image has compression = \"%s\", but support not compiled in\n",
+ compression);
+ return -ENOSYS;
+ }
+
+ data_len = uncompress_buf_to_buf(data, data_len, &uc_data,
+ fit_uncompress_error_fn);
+ if (data_len < 0) {
+ pr_err("data couldn't be decompressed\n");
+ return data_len;
+ }
+
+ data = uc_data;
+
+ /* associate buffer with FIT, so it's not leaked */
+ __of_new_property(image, "uncompressed-data", uc_data, data_len);
+ }
+
*outdata = data;
*outsize = data_len;
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 2247b5a1a3..37c94d00bf 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2221,8 +2221,8 @@ struct device_node *of_new_node(struct device_node *parent, const char *name)
return node;
}
-static struct property *__of_new_property(struct device_node *node, const char *name,
- void *data, int len)
+struct property *__of_new_property(struct device_node *node, const char *name,
+ void *data, int len)
{
struct property *prop;
diff --git a/include/of.h b/include/of.h
index 4aadbb7edb..00b2bbd677 100644
--- a/include/of.h
+++ b/include/of.h
@@ -136,6 +136,8 @@ extern struct property *of_new_property(struct device_node *node,
extern struct property *of_new_property_const(struct device_node *node,
const char *name,
const void *data, int len);
+extern struct property *__of_new_property(struct device_node *node,
+ const char *name, void *data, int len);
extern void of_delete_property(struct property *pp);
extern struct device_node *of_find_node_by_name(struct device_node *from,
@@ -520,6 +522,12 @@ static inline struct property *of_new_property(struct device_node *node,
return NULL;
}
+static inline struct property *__of_new_property(struct device_node *node,
+ const char *name, void *data, int len)
+{
+ return NULL;
+}
+
static inline void of_delete_property(struct property *pp)
{
}
diff --git a/include/uncompress.h b/include/uncompress.h
index 4bdb03d4f5..72ba1dfda6 100644
--- a/include/uncompress.h
+++ b/include/uncompress.h
@@ -15,6 +15,12 @@ int uncompress_fd_to_fd(int infd, int outfd,
int uncompress_fd_to_buf(int infd, void *output,
void(*error_fn)(char *x));
+int uncompress_buf_to_fd(const void *input, size_t input_len,
+ int outfd, void(*error_fn)(char *x));
+
+ssize_t uncompress_buf_to_buf(const void *input, size_t input_len,
+ void **buf, void(*error_fn)(char *x));
+
void uncompress_err_stdout(char *);
#endif /* __UNCOMPRESS_H */
diff --git a/lib/uncompress.c b/lib/uncompress.c
index 5c0d1e9f4d..0608e9f9d3 100644
--- a/lib/uncompress.c
+++ b/lib/uncompress.c
@@ -172,3 +172,43 @@ int uncompress_fd_to_buf(int infd, void *output,
return uncompress(NULL, 0, fill_fd, NULL, output, NULL, error_fn);
}
+
+int uncompress_buf_to_fd(const void *input, size_t input_len,
+ int outfd, void(*error_fn)(char *x))
+{
+ uncompress_outfd = outfd;
+
+ return uncompress((void *)input, input_len, NULL, flush_fd,
+ NULL, NULL, error_fn);
+}
+
+ssize_t uncompress_buf_to_buf(const void *input, size_t input_len,
+ void **buf, void(*error_fn)(char *x))
+{
+ char *dstpath;
+ size_t size;
+ int outfd, ret;
+
+ dstpath = make_temp("data-uncompressed");
+ if (!dstpath)
+ return -ENOMEM;
+
+ outfd = open(dstpath, O_CREAT | O_WRONLY);
+ if (outfd < 0) {
+ ret = -ENODEV;
+ goto free_temp;
+ }
+
+ ret = uncompress_buf_to_fd(input, input_len, outfd, uncompress_err_stdout);
+ if (ret)
+ goto close_outfd;
+
+ *buf = read_file(dstpath, &size);
+close_outfd:
+ close(outfd);
+ unlink(dstpath);
+free_temp:
+ free(dstpath);
+
+ return ret ?: size;
+}