|
@@ -15,6 +15,7 @@
|
|
#include <serial.h>
|
|
#include <serial.h>
|
|
#include <asm/sections.h>
|
|
#include <asm/sections.h>
|
|
#include <linux/ctype.h>
|
|
#include <linux/ctype.h>
|
|
|
|
+#include <linux/lzo.h>
|
|
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
|
|
@@ -1203,9 +1204,66 @@ int fdtdec_setup_memory_banksize(void)
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
|
|
|
|
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT_GZIP) ||\
|
|
|
|
+ CONFIG_IS_ENABLED(MULTI_DTB_FIT_LZO)
|
|
|
|
+static int uncompress_blob(const void *src, ulong sz_src, void **dstp)
|
|
|
|
+{
|
|
|
|
+ size_t sz_out = CONFIG_SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ;
|
|
|
|
+ ulong sz_in = sz_src;
|
|
|
|
+ void *dst;
|
|
|
|
+ int rc;
|
|
|
|
+
|
|
|
|
+ if (CONFIG_IS_ENABLED(GZIP))
|
|
|
|
+ if (gzip_parse_header(src, sz_in) < 0)
|
|
|
|
+ return -1;
|
|
|
|
+ if (CONFIG_IS_ENABLED(LZO))
|
|
|
|
+ if (!lzop_is_valid_header(src))
|
|
|
|
+ return -EBADMSG;
|
|
|
|
+
|
|
|
|
+ if (CONFIG_IS_ENABLED(MULTI_DTB_FIT_DYN_ALLOC)) {
|
|
|
|
+ dst = malloc(sz_out);
|
|
|
|
+ if (!dst) {
|
|
|
|
+ puts("uncompress_blob: Unable to allocate memory\n");
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT_USER_DEFINED_AREA)
|
|
|
|
+ dst = (void *)CONFIG_VAL(MULTI_DTB_FIT_USER_DEF_ADDR);
|
|
|
|
+# else
|
|
|
|
+ return -ENOTSUPP;
|
|
|
|
+# endif
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (CONFIG_IS_ENABLED(GZIP))
|
|
|
|
+ rc = gunzip(dst, sz_out, (u8 *)src, &sz_in);
|
|
|
|
+ else if (CONFIG_IS_ENABLED(LZO))
|
|
|
|
+ rc = lzop_decompress(src, sz_in, dst, &sz_out);
|
|
|
|
+
|
|
|
|
+ if (rc < 0) {
|
|
|
|
+ /* not a valid compressed blob */
|
|
|
|
+ puts("uncompress_blob: Unable to uncompress\n");
|
|
|
|
+ if (CONFIG_IS_ENABLED(MULTI_DTB_FIT_DYN_ALLOC))
|
|
|
|
+ free(dst);
|
|
|
|
+ return -EBADMSG;
|
|
|
|
+ }
|
|
|
|
+ *dstp = dst;
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+# else
|
|
|
|
+static int uncompress_blob(const void *src, ulong sz_src, void **dstp)
|
|
|
|
+{
|
|
|
|
+ return -ENOTSUPP;
|
|
|
|
+}
|
|
|
|
+# endif
|
|
|
|
+#endif
|
|
|
|
+
|
|
int fdtdec_setup(void)
|
|
int fdtdec_setup(void)
|
|
{
|
|
{
|
|
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
|
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
|
|
|
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
|
|
|
|
+ void *fdt_blob;
|
|
|
|
+# endif
|
|
# ifdef CONFIG_OF_EMBED
|
|
# ifdef CONFIG_OF_EMBED
|
|
/* Get a pointer to the FDT */
|
|
/* Get a pointer to the FDT */
|
|
gd->fdt_blob = __dtb_dt_begin;
|
|
gd->fdt_blob = __dtb_dt_begin;
|
|
@@ -1216,15 +1274,6 @@ int fdtdec_setup(void)
|
|
gd->fdt_blob = (ulong *)&_image_binary_end;
|
|
gd->fdt_blob = (ulong *)&_image_binary_end;
|
|
else
|
|
else
|
|
gd->fdt_blob = (ulong *)&__bss_end;
|
|
gd->fdt_blob = (ulong *)&__bss_end;
|
|
-
|
|
|
|
-# elif defined CONFIG_MULTI_DTB_FIT
|
|
|
|
- gd->fdt_blob = locate_dtb_in_fit(&_end);
|
|
|
|
-
|
|
|
|
- if (gd->fdt_blob == NULL || gd->fdt_blob <= ((void *)&_end)) {
|
|
|
|
- puts("Failed to find proper dtb in embedded FIT Image\n");
|
|
|
|
- return -1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
# else
|
|
# else
|
|
/* FDT is at end of image */
|
|
/* FDT is at end of image */
|
|
gd->fdt_blob = (ulong *)&_end;
|
|
gd->fdt_blob = (ulong *)&_end;
|
|
@@ -1243,7 +1292,27 @@ int fdtdec_setup(void)
|
|
gd->fdt_blob = (void *)env_get_ulong("fdtcontroladdr", 16,
|
|
gd->fdt_blob = (void *)env_get_ulong("fdtcontroladdr", 16,
|
|
(uintptr_t)gd->fdt_blob);
|
|
(uintptr_t)gd->fdt_blob);
|
|
# endif
|
|
# endif
|
|
|
|
+
|
|
|
|
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
|
|
|
|
+ /*
|
|
|
|
+ * Try and uncompress the blob.
|
|
|
|
+ * Unfortunately there is no way to know how big the input blob really
|
|
|
|
+ * is. So let us set the maximum input size arbitrarily high. 16MB
|
|
|
|
+ * ought to be more than enough for packed DTBs.
|
|
|
|
+ */
|
|
|
|
+ if (uncompress_blob(gd->fdt_blob, 0x1000000, &fdt_blob) == 0)
|
|
|
|
+ gd->fdt_blob = fdt_blob;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Check if blob is a FIT images containings DTBs.
|
|
|
|
+ * If so, pick the most relevant
|
|
|
|
+ */
|
|
|
|
+ fdt_blob = locate_dtb_in_fit(gd->fdt_blob);
|
|
|
|
+ if (fdt_blob)
|
|
|
|
+ gd->fdt_blob = fdt_blob;
|
|
|
|
+# endif
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
return fdtdec_prepare_fdt();
|
|
return fdtdec_prepare_fdt();
|
|
}
|
|
}
|
|
|
|
|