Some devices have uImage headers after some extra headers (e.g. Edimax
devices). To support such cases our verify callback function should be
allowed to return header offset, not just a boolean value.

Signed-off-by: Rafał Miłecki <zaj...@gmail.com>
---
Hi Tomasz,

I was looking at the patch you submitted
PATCH [kernel]: proper support for Edimax uimages
http://patchwork.openwrt.org/patch/6555/
and was thinking about some better solution.

I didn't like the fact that you added Edimax specific workaround to the
supposed-to-be-generic __mtdsplit_parse_uimage.

So I came with the idea of modifying our callback function. With this
patch you should be able to re-write your uimage_verify_edimax to simply
return 20 instead of true.

Of course we will also need to do something like:
header_offset = find_header(buf, buf_size);
header = offset + header_offset;
---
 .../generic/files/drivers/mtd/mtdsplit_uimage.c    | 37 +++++++++++++++-------
 1 file changed, 26 insertions(+), 11 deletions(-)

diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit_uimage.c 
b/target/linux/generic/files/drivers/mtd/mtdsplit_uimage.c
index 7dad63c..2f723bd 100644
--- a/target/linux/generic/files/drivers/mtd/mtdsplit_uimage.c
+++ b/target/linux/generic/files/drivers/mtd/mtdsplit_uimage.c
@@ -71,10 +71,16 @@ read_uimage_header(struct mtd_info *mtd, size_t offset,
        return 0;
 }
 
+/**
+ * __mtdsplit_parse_uimage - scan partition and create kernel + rootfs parts
+ *
+ * @find_header: function to call for a block of data that will return offset
+ *      of a valid uImage header if found
+ */
 static int __mtdsplit_parse_uimage(struct mtd_info *master,
                                   struct mtd_partition **pparts,
                                   struct mtd_part_parser_data *data,
-                                  bool (*verify)(struct uimage_header *hdr))
+                                  size_t (*find_header)(u_char *buf, size_t 
len))
 {
        struct mtd_partition *parts;
        struct uimage_header *header;
@@ -106,11 +112,16 @@ static int __mtdsplit_parse_uimage(struct mtd_info 
*master,
                if (ret)
                        continue;
 
-               if (!verify(header)) {
+               ret = find_header((u_char *)header, sizeof(*header));
+               if (ret < 0) {
                        pr_debug("no valid uImage found in \"%s\" at offset 
%llx\n",
                                 master->name, (unsigned long long) offset);
                        continue;
                }
+               if (ret > 0) {
+                       pr_warn("extra header offsets are not supported yet\n");
+                       continue;
+               }
 
                uimage_size = sizeof(*header) + be32_to_cpu(header->ih_size);
                if ((offset + uimage_size) > master->size) {
@@ -189,28 +200,30 @@ err_free_parts:
        return ret;
 }
 
-static bool uimage_verify_default(struct uimage_header *header)
+static size_t uimage_verify_default(u_char *buf, size_t len)
 {
+       struct uimage_header *header = (struct uimage_header *)buf;
+
        /* default sanity checks */
        if (be32_to_cpu(header->ih_magic) != IH_MAGIC) {
                pr_debug("invalid uImage magic: %08x\n",
                         be32_to_cpu(header->ih_magic));
-               return false;
+               return -EINVAL;
        }
 
        if (header->ih_os != IH_OS_LINUX) {
                pr_debug("invalid uImage OS: %08x\n",
                         be32_to_cpu(header->ih_os));
-               return false;
+               return -EINVAL;
        }
 
        if (header->ih_type != IH_TYPE_KERNEL) {
                pr_debug("invalid uImage type: %08x\n",
                         be32_to_cpu(header->ih_type));
-               return false;
+               return -EINVAL;
        }
 
-       return true;
+       return 0;
 }
 
 static int
@@ -236,9 +249,11 @@ static struct mtd_part_parser uimage_generic_parser = {
 #define FW_MAGIC_WNDR3700      0x33373030
 #define FW_MAGIC_WNDR3700V2    0x33373031
 
-static bool uimage_verify_wndr3700(struct uimage_header *header)
+static size_t uimage_verify_wndr3700(u_char *buf, size_t len)
 {
+       struct uimage_header *header = (struct uimage_header *)buf;
        uint8_t expected_type = IH_TYPE_FILESYSTEM;
+
        switch be32_to_cpu(header->ih_magic) {
        case FW_MAGIC_WNR612V2:
        case FW_MAGIC_WNR2000V3:
@@ -250,14 +265,14 @@ static bool uimage_verify_wndr3700(struct uimage_header 
*header)
                expected_type = IH_TYPE_KERNEL;
                break;
        default:
-               return false;
+               return -EINVAL;
        }
 
        if (header->ih_os != IH_OS_LINUX ||
            header->ih_type != expected_type)
-               return false;
+               return -EINVAL;
 
-       return true;
+       return 0;
 }
 
 static int
-- 
1.8.4.5
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to