diff mbox

[OpenWrt-Devel] kernel: mtdsplit_uimage: use more generic header verify function

Message ID 1418514066-6934-1-git-send-email-zajec5@gmail.com
State Changes Requested
Headers show

Commit Message

Rafał Miłecki Dec. 13, 2014, 11:41 p.m. UTC
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 <zajec5@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(-)

Comments

Felix Fietkau Dec. 16, 2014, 4:01 p.m. UTC | #1
On 2014-12-14 00:41, Rafał Miłecki wrote:
> 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 <zajec5@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))
I believe the return type you're looking for is ssize_t, not size_t.

- Felix
diff mbox

Patch

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