diff options
author | Gabor Juhos <juhosg@openwrt.org> | 2014-01-24 17:14:59 +0000 |
---|---|---|
committer | Gabor Juhos <juhosg@openwrt.org> | 2014-01-24 17:14:59 +0000 |
commit | 89d60314e766e2d579bdbf63227c601c0eedfef6 (patch) | |
tree | dcb6e729e229bc77b71270e85562f7fbcdd5c225 /target/linux/generic/files/drivers | |
parent | 64f3676a25d7d1b8b5417dd9f75eaca1798a2d45 (diff) | |
download | upstream-89d60314e766e2d579bdbf63227c601c0eedfef6.tar.gz upstream-89d60314e766e2d579bdbf63227c601c0eedfef6.tar.bz2 upstream-89d60314e766e2d579bdbf63227c601c0eedfef6.zip |
kernel/3.1x: add split code for LZMA compressed kernel based firmwares
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
SVN-Revision: 39387
Diffstat (limited to 'target/linux/generic/files/drivers')
-rw-r--r-- | target/linux/generic/files/drivers/mtd/mtdsplit_lzma.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit_lzma.c b/target/linux/generic/files/drivers/mtd/mtdsplit_lzma.c new file mode 100644 index 0000000000..d23060a7d5 --- /dev/null +++ b/target/linux/generic/files/drivers/mtd/mtdsplit_lzma.c @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2014 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> + +#include <asm/unaligned.h> + +#include "mtdsplit.h" + +#define LZMA_NR_PARTS 2 +#define LZMA_PROPERTIES_SIZE 5 + +struct lzma_header { + u8 props[LZMA_PROPERTIES_SIZE]; + u8 size_low[4]; + u8 size_high[4]; +}; + +static int mtdsplit_parse_lzma(struct mtd_info *master, + struct mtd_partition **pparts, + struct mtd_part_parser_data *data) +{ + struct lzma_header hdr; + size_t hdr_len, retlen; + size_t rootfs_offset; + u32 t; + struct mtd_partition *parts; + int err; + + hdr_len = sizeof(hdr); + err = mtd_read(master, 0, hdr_len, &retlen, (void *) &hdr); + if (err) + return err; + + if (retlen != hdr_len) + return -EIO; + + /* verify LZMA properties */ + if (hdr.props[0] >= (9 * 5 * 5)) + return -EINVAL; + + t = get_unaligned_le32(&hdr.props[1]); + if (!is_power_of_2(t)) + return -EINVAL; + + t = get_unaligned_le32(&hdr.size_high); + if (t) + return -EINVAL; + + err = mtd_find_rootfs_from(master, master->erasesize, + master->size, &rootfs_offset); + if (err) + return err; + + parts = kzalloc(LZMA_NR_PARTS * sizeof(*parts), GFP_KERNEL); + if (!parts) + return -ENOMEM; + + parts[0].name = KERNEL_PART_NAME; + parts[0].offset = 0; + parts[0].size = rootfs_offset; + + parts[1].name = ROOTFS_PART_NAME; + parts[1].offset = rootfs_offset; + parts[1].size = master->size - rootfs_offset; + + *pparts = parts; + return LZMA_NR_PARTS; +} + +static struct mtd_part_parser mtdsplit_lzma_parser = { + .owner = THIS_MODULE, + .name = "lzma-fw", + .parse_fn = mtdsplit_parse_lzma, + .type = MTD_PARSER_TYPE_FIRMWARE, +}; + +static int +mtdsplit_lzma_init(void) +{ + return register_mtd_parser(&mtdsplit_lzma_parser); +} + +subsys_initcall(mtdsplit_lzma_init); |