Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright © 2007 Eugene Konev <ejka@openwrt.org>
0004  *
0005  * TI AR7 flash partition table.
0006  * Based on ar7 map by Felix Fietkau <nbd@openwrt.org>
0007  */
0008 
0009 #include <linux/kernel.h>
0010 #include <linux/slab.h>
0011 
0012 #include <linux/mtd/mtd.h>
0013 #include <linux/mtd/partitions.h>
0014 #include <linux/memblock.h>
0015 #include <linux/module.h>
0016 
0017 #include <uapi/linux/magic.h>
0018 
0019 #define AR7_PARTS   4
0020 #define ROOT_OFFSET 0xe0000
0021 
0022 #define LOADER_MAGIC1   le32_to_cpu(0xfeedfa42)
0023 #define LOADER_MAGIC2   le32_to_cpu(0xfeed1281)
0024 
0025 struct ar7_bin_rec {
0026     unsigned int checksum;
0027     unsigned int length;
0028     unsigned int address;
0029 };
0030 
0031 static int create_mtd_partitions(struct mtd_info *master,
0032                  const struct mtd_partition **pparts,
0033                  struct mtd_part_parser_data *data)
0034 {
0035     struct ar7_bin_rec header;
0036     unsigned int offset;
0037     size_t len;
0038     unsigned int pre_size = master->erasesize, post_size = 0;
0039     unsigned int root_offset = ROOT_OFFSET;
0040 
0041     int retries = 10;
0042     struct mtd_partition *ar7_parts;
0043 
0044     ar7_parts = kcalloc(AR7_PARTS, sizeof(*ar7_parts), GFP_KERNEL);
0045     if (!ar7_parts)
0046         return -ENOMEM;
0047     ar7_parts[0].name = "loader";
0048     ar7_parts[0].offset = 0;
0049     ar7_parts[0].size = master->erasesize;
0050     ar7_parts[0].mask_flags = MTD_WRITEABLE;
0051 
0052     ar7_parts[1].name = "config";
0053     ar7_parts[1].offset = 0;
0054     ar7_parts[1].size = master->erasesize;
0055     ar7_parts[1].mask_flags = 0;
0056 
0057     do { /* Try 10 blocks starting from master->erasesize */
0058         offset = pre_size;
0059         mtd_read(master, offset, sizeof(header), &len,
0060              (uint8_t *)&header);
0061         if (!strncmp((char *)&header, "TIENV0.8", 8))
0062             ar7_parts[1].offset = pre_size;
0063         if (header.checksum == LOADER_MAGIC1)
0064             break;
0065         if (header.checksum == LOADER_MAGIC2)
0066             break;
0067         pre_size += master->erasesize;
0068     } while (retries--);
0069 
0070     pre_size = offset;
0071 
0072     if (!ar7_parts[1].offset) {
0073         ar7_parts[1].offset = master->size - master->erasesize;
0074         post_size = master->erasesize;
0075     }
0076 
0077     switch (header.checksum) {
0078     case LOADER_MAGIC1:
0079         while (header.length) {
0080             offset += sizeof(header) + header.length;
0081             mtd_read(master, offset, sizeof(header), &len,
0082                  (uint8_t *)&header);
0083         }
0084         root_offset = offset + sizeof(header) + 4;
0085         break;
0086     case LOADER_MAGIC2:
0087         while (header.length) {
0088             offset += sizeof(header) + header.length;
0089             mtd_read(master, offset, sizeof(header), &len,
0090                  (uint8_t *)&header);
0091         }
0092         root_offset = offset + sizeof(header) + 4 + 0xff;
0093         root_offset &= ~(uint32_t)0xff;
0094         break;
0095     default:
0096         printk(KERN_WARNING "Unknown magic: %08x\n", header.checksum);
0097         break;
0098     }
0099 
0100     mtd_read(master, root_offset, sizeof(header), &len, (u8 *)&header);
0101     if (header.checksum != SQUASHFS_MAGIC) {
0102         root_offset += master->erasesize - 1;
0103         root_offset &= ~(master->erasesize - 1);
0104     }
0105 
0106     ar7_parts[2].name = "linux";
0107     ar7_parts[2].offset = pre_size;
0108     ar7_parts[2].size = master->size - pre_size - post_size;
0109     ar7_parts[2].mask_flags = 0;
0110 
0111     ar7_parts[3].name = "rootfs";
0112     ar7_parts[3].offset = root_offset;
0113     ar7_parts[3].size = master->size - root_offset - post_size;
0114     ar7_parts[3].mask_flags = 0;
0115 
0116     *pparts = ar7_parts;
0117     return AR7_PARTS;
0118 }
0119 
0120 static struct mtd_part_parser ar7_parser = {
0121     .parse_fn = create_mtd_partitions,
0122     .name = "ar7part",
0123 };
0124 module_mtd_part_parser(ar7_parser);
0125 
0126 MODULE_LICENSE("GPL");
0127 MODULE_AUTHOR(  "Felix Fietkau <nbd@openwrt.org>, "
0128         "Eugene Konev <ejka@openwrt.org>");
0129 MODULE_DESCRIPTION("MTD partitioning for TI AR7");