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

Rafał Miłecki zajec5 at gmail.com
Sat Dec 13 18:41:06 EST 2014


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 at 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 at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel


More information about the openwrt-devel mailing list