kernel: mtdsplit_uimage: add "openwrt, ih-magic" device-tree property
authorBjørn Mork <bjorn@mork.no>
Wed, 20 Jan 2021 17:36:47 +0000 (18:36 +0100)
committerPetr Štetiar <ynezz@true.cz>
Fri, 22 Jan 2021 20:03:11 +0000 (21:03 +0100)
Many devices use uimages with non-standard magic values. Let
device tree override the default magic.

Signed-off-by: Bjørn Mork <bjorn@mork.no>
target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_uimage.c

index f5e48c661e8fc8a05ba26da44675b97e13fc3947..58c40e9ec70b5a88452a119c0ad13795a13be443 100644 (file)
@@ -69,13 +69,17 @@ read_uimage_header(struct mtd_info *mtd, size_t offset, u_char *buf,
        return 0;
 }
 
        return 0;
 }
 
-static void uimage_parse_dt(struct mtd_info *master, int *extralen)
+static void uimage_parse_dt(struct mtd_info *master, int *extralen, u32 *ih_magic)
 {
        struct device_node *np = mtd_get_of_node(master);
 
        if (!np || !of_device_is_compatible(np, "openwrt,uimage"))
                return;
 {
        struct device_node *np = mtd_get_of_node(master);
 
        if (!np || !of_device_is_compatible(np, "openwrt,uimage"))
                return;
-       of_property_read_u32(np, "openwrt,padding", extralen);
+
+       if (!of_property_read_u32(np, "openwrt,padding", extralen))
+               pr_debug("got openwrt,padding=%d from device-tree\n", *extralen);
+       if (!of_property_read_u32(np, "openwrt,ih-magic", ih_magic))
+               pr_debug("got openwrt,ih-magic=%08x from device-tree\n", *ih_magic);
 }
 
 /**
 }
 
 /**
@@ -87,7 +91,7 @@ static void uimage_parse_dt(struct mtd_info *master, int *extralen)
 static int __mtdsplit_parse_uimage(struct mtd_info *master,
                   const struct mtd_partition **pparts,
                   struct mtd_part_parser_data *data,
 static int __mtdsplit_parse_uimage(struct mtd_info *master,
                   const struct mtd_partition **pparts,
                   struct mtd_part_parser_data *data,
-                  ssize_t (*find_header)(u_char *buf, size_t len))
+                  ssize_t (*find_header)(u_char *buf, size_t len, u32 ih_magic))
 {
        struct mtd_partition *parts;
        u_char *buf;
 {
        struct mtd_partition *parts;
        u_char *buf;
@@ -100,6 +104,7 @@ static int __mtdsplit_parse_uimage(struct mtd_info *master,
        int uimage_part, rf_part;
        int ret;
        int extralen = 0;
        int uimage_part, rf_part;
        int ret;
        int extralen = 0;
+       u32 ih_magic = IH_MAGIC;
        enum mtdsplit_part_type type;
 
        nr_parts = 2;
        enum mtdsplit_part_type type;
 
        nr_parts = 2;
@@ -113,7 +118,7 @@ static int __mtdsplit_parse_uimage(struct mtd_info *master,
                goto err_free_parts;
        }
 
                goto err_free_parts;
        }
 
-       uimage_parse_dt(master, &extralen);
+       uimage_parse_dt(master, &extralen, &ih_magic);
 
        /* find uImage on erase block boundaries */
        for (offset = 0; offset < master->size; offset += master->erasesize) {
 
        /* find uImage on erase block boundaries */
        for (offset = 0; offset < master->size; offset += master->erasesize) {
@@ -125,7 +130,7 @@ static int __mtdsplit_parse_uimage(struct mtd_info *master,
                if (ret)
                        continue;
 
                if (ret)
                        continue;
 
-               ret = find_header(buf, MAX_HEADER_LEN);
+               ret = find_header(buf, MAX_HEADER_LEN, ih_magic);
                if (ret < 0) {
                        pr_debug("no valid uImage found in \"%s\" at offset %llx\n",
                                 master->name, (unsigned long long) offset);
                if (ret < 0) {
                        pr_debug("no valid uImage found in \"%s\" at offset %llx\n",
                                 master->name, (unsigned long long) offset);
@@ -213,26 +218,26 @@ err_free_parts:
        return ret;
 }
 
        return ret;
 }
 
-static ssize_t uimage_verify_default(u_char *buf, size_t len)
+static ssize_t uimage_verify_default(u_char *buf, size_t len, u32 ih_magic)
 {
        struct uimage_header *header = (struct uimage_header *)buf;
 
        /* default sanity checks */
 {
        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));
+       if (be32_to_cpu(header->ih_magic) != ih_magic) {
+               pr_debug("invalid uImage magic: %08x != %08x\n",
+                        be32_to_cpu(header->ih_magic), ih_magic);
                return -EINVAL;
        }
 
        if (header->ih_os != IH_OS_LINUX) {
                return -EINVAL;
        }
 
        if (header->ih_os != IH_OS_LINUX) {
-               pr_debug("invalid uImage OS: %08x\n",
-                        be32_to_cpu(header->ih_os));
+               pr_debug("invalid uImage OS: %08x != %08x\n",
+                        be32_to_cpu(header->ih_os), IH_OS_LINUX);
                return -EINVAL;
        }
 
        if (header->ih_type != IH_TYPE_KERNEL) {
                return -EINVAL;
        }
 
        if (header->ih_type != IH_TYPE_KERNEL) {
-               pr_debug("invalid uImage type: %08x\n",
-                        be32_to_cpu(header->ih_type));
+               pr_debug("invalid uImage type: %08x != %08x\n",
+                        be32_to_cpu(header->ih_type), IH_TYPE_KERNEL);
                return -EINVAL;
        }
 
                return -EINVAL;
        }
 
@@ -274,7 +279,7 @@ static struct mtd_part_parser uimage_generic_parser = {
 #define FW_MAGIC_WNDR3700V2    0x33373031
 #define FW_MAGIC_WPN824N       0x31313030
 
 #define FW_MAGIC_WNDR3700V2    0x33373031
 #define FW_MAGIC_WPN824N       0x31313030
 
-static ssize_t uimage_verify_wndr3700(u_char *buf, size_t len)
+static ssize_t uimage_verify_wndr3700(u_char *buf, size_t len, u32 ih_magic)
 {
        struct uimage_header *header = (struct uimage_header *)buf;
        uint8_t expected_type = IH_TYPE_FILESYSTEM;
 {
        struct uimage_header *header = (struct uimage_header *)buf;
        uint8_t expected_type = IH_TYPE_FILESYSTEM;
@@ -336,7 +341,7 @@ static struct mtd_part_parser uimage_netgear_parser = {
 #define FW_MAGIC_SG8208M       0x00000006
 #define FW_MAGIC_SG8310PM      0x83000006
 
 #define FW_MAGIC_SG8208M       0x00000006
 #define FW_MAGIC_SG8310PM      0x83000006
 
-static ssize_t uimage_verify_allnet(u_char *buf, size_t len)
+static ssize_t uimage_verify_allnet(u_char *buf, size_t len, u32 ih_magic)
 {
        struct uimage_header *header = (struct uimage_header *)buf;
 
 {
        struct uimage_header *header = (struct uimage_header *)buf;
 
@@ -383,7 +388,7 @@ static struct mtd_part_parser uimage_allnet_parser = {
 #define FW_EDIMAX_OFFSET       20
 #define FW_MAGIC_EDIMAX                0x43535953
 
 #define FW_EDIMAX_OFFSET       20
 #define FW_MAGIC_EDIMAX                0x43535953
 
-static ssize_t uimage_find_edimax(u_char *buf, size_t len)
+static ssize_t uimage_find_edimax(u_char *buf, size_t len, u32 ih_magic)
 {
        u32 *magic;
 
 {
        u32 *magic;
 
@@ -396,7 +401,7 @@ static ssize_t uimage_find_edimax(u_char *buf, size_t len)
        if (be32_to_cpu(*magic) != FW_MAGIC_EDIMAX)
                return -EINVAL;
 
        if (be32_to_cpu(*magic) != FW_MAGIC_EDIMAX)
                return -EINVAL;
 
-       if (!uimage_verify_default(buf + FW_EDIMAX_OFFSET, len))
+       if (!uimage_verify_default(buf + FW_EDIMAX_OFFSET, len, ih_magic))
                return FW_EDIMAX_OFFSET;
 
        return -EINVAL;
                return FW_EDIMAX_OFFSET;
 
        return -EINVAL;
@@ -430,7 +435,7 @@ static struct mtd_part_parser uimage_edimax_parser = {
 
 #define IH_MAGIC_OKLI  0x4f4b4c49
 
 
 #define IH_MAGIC_OKLI  0x4f4b4c49
 
-static ssize_t uimage_verify_okli(u_char *buf, size_t len)
+static ssize_t uimage_verify_okli(u_char *buf, size_t len, u32 ih_magic)
 {
        struct uimage_header *header = (struct uimage_header *)buf;
 
 {
        struct uimage_header *header = (struct uimage_header *)buf;