X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=target%2Flinux%2Far71xx%2Ffiles%2Fdrivers%2Fmtd%2Ftplinkpart.c;h=1b94163b8330df834697c1b2b35b655adfc83a2f;hb=7bbf4117c6fe4b764d9d7c62fb2bcf6dd93bff2c;hp=7b2ac7e40dc3ce649bf078198569cd8cfbfe16f5;hpb=514b1167c9157e9c96db40f95098b2b15558915a;p=openwrt%2Fstaging%2Fhauke.git diff --git a/target/linux/ar71xx/files/drivers/mtd/tplinkpart.c b/target/linux/ar71xx/files/drivers/mtd/tplinkpart.c index 7b2ac7e40d..1b94163b83 100644 --- a/target/linux/ar71xx/files/drivers/mtd/tplinkpart.c +++ b/target/linux/ar71xx/files/drivers/mtd/tplinkpart.c @@ -8,18 +8,23 @@ */ #include +#include #include #include +#include #include #include +#include #define TPLINK_NUM_PARTS 5 #define TPLINK_HEADER_V1 0x01000000 +#define TPLINK_HEADER_V2 0x02000000 #define MD5SUM_LEN 16 #define TPLINK_ART_LEN 0x10000 #define TPLINK_KERNEL_OFFS 0x20000 +#define TPLINK_64K_KERNEL_OFFS 0x10000 struct tplink_fw_header { uint32_t version; /* header version */ @@ -58,8 +63,8 @@ tplink_read_header(struct mtd_info *mtd, size_t offset) goto err; header_len = sizeof(struct tplink_fw_header); - ret = mtd->read(mtd, offset, header_len, &retlen, - (unsigned char *) header); + ret = mtd_read(mtd, offset, header_len, &retlen, + (unsigned char *) header); if (ret) goto err_free_header; @@ -68,7 +73,7 @@ tplink_read_header(struct mtd_info *mtd, size_t offset) /* sanity checks */ t = be32_to_cpu(header->version); - if (t != TPLINK_HEADER_V1) + if ((t != TPLINK_HEADER_V1) && (t != TPLINK_HEADER_V2)) goto err_free_header; t = be32_to_cpu(header->kernel_ofs); @@ -83,16 +88,42 @@ err: return NULL; } -static int tplink_parse_partitions(struct mtd_info *master, +static int tplink_check_rootfs_magic(struct mtd_info *mtd, size_t offset) +{ + u32 magic; + size_t retlen; + int ret; + + ret = mtd_read(mtd, offset, sizeof(magic), &retlen, + (unsigned char *) &magic); + if (ret) + return ret; + + if (retlen != sizeof(magic)) + return -EIO; + + if (le32_to_cpu(magic) != SQUASHFS_MAGIC && + magic != 0x19852003) + return -EINVAL; + + return 0; +} + +static int tplink_parse_partitions_offset(struct mtd_info *master, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0) struct mtd_partition **pparts, - unsigned long origin) +#else + const struct mtd_partition **pparts, +#endif + struct mtd_part_parser_data *data, + size_t offset) { struct mtd_partition *parts; struct tplink_fw_header *header; int nr_parts; - size_t offset; size_t art_offset; size_t rootfs_offset; + size_t squashfs_offset; int ret; nr_parts = TPLINK_NUM_PARTS; @@ -102,8 +133,6 @@ static int tplink_parse_partitions(struct mtd_info *master, goto err; } - offset = TPLINK_KERNEL_OFFS; - header = tplink_read_header(master, offset); if (!header) { pr_notice("%s: no TP-Link header found\n", master->name); @@ -111,7 +140,15 @@ static int tplink_parse_partitions(struct mtd_info *master, goto err_free_parts; } - rootfs_offset = offset + be32_to_cpu(header->rootfs_ofs); + squashfs_offset = offset + sizeof(struct tplink_fw_header) + + be32_to_cpu(header->kernel_len); + + ret = tplink_check_rootfs_magic(master, squashfs_offset); + if (ret == 0) + rootfs_offset = squashfs_offset; + else + rootfs_offset = offset + be32_to_cpu(header->rootfs_ofs); + art_offset = master->size - TPLINK_ART_LEN; parts[0].name = "u-boot"; @@ -148,15 +185,48 @@ err: return ret; } +static int tplink_parse_partitions(struct mtd_info *master, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0) + struct mtd_partition **pparts, +#else + const struct mtd_partition **pparts, +#endif + struct mtd_part_parser_data *data) +{ + return tplink_parse_partitions_offset(master, pparts, data, + TPLINK_KERNEL_OFFS); +} + +static int tplink_parse_64k_partitions(struct mtd_info *master, +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0) + struct mtd_partition **pparts, +#else + const struct mtd_partition **pparts, +#endif + struct mtd_part_parser_data *data) +{ + return tplink_parse_partitions_offset(master, pparts, data, + TPLINK_64K_KERNEL_OFFS); +} + static struct mtd_part_parser tplink_parser = { .owner = THIS_MODULE, .parse_fn = tplink_parse_partitions, .name = "tp-link", }; +static struct mtd_part_parser tplink_64k_parser = { + .owner = THIS_MODULE, + .parse_fn = tplink_parse_64k_partitions, + .name = "tp-link-64k", +}; + static int __init tplink_parser_init(void) { - return register_mtd_parser(&tplink_parser); + register_mtd_parser(&tplink_parser); + register_mtd_parser(&tplink_64k_parser); + + return 0; } module_init(tplink_parser_init);