root/drivers/mtd/parsers/ar7part.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. create_mtd_partitions

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright © 2007 Eugene Konev <ejka@openwrt.org>
   4  *
   5  * TI AR7 flash partition table.
   6  * Based on ar7 map by Felix Fietkau <nbd@openwrt.org>
   7  */
   8 
   9 #include <linux/kernel.h>
  10 #include <linux/slab.h>
  11 
  12 #include <linux/mtd/mtd.h>
  13 #include <linux/mtd/partitions.h>
  14 #include <linux/memblock.h>
  15 #include <linux/module.h>
  16 
  17 #include <uapi/linux/magic.h>
  18 
  19 #define AR7_PARTS       4
  20 #define ROOT_OFFSET     0xe0000
  21 
  22 #define LOADER_MAGIC1   le32_to_cpu(0xfeedfa42)
  23 #define LOADER_MAGIC2   le32_to_cpu(0xfeed1281)
  24 
  25 struct ar7_bin_rec {
  26         unsigned int checksum;
  27         unsigned int length;
  28         unsigned int address;
  29 };
  30 
  31 static int create_mtd_partitions(struct mtd_info *master,
  32                                  const struct mtd_partition **pparts,
  33                                  struct mtd_part_parser_data *data)
  34 {
  35         struct ar7_bin_rec header;
  36         unsigned int offset;
  37         size_t len;
  38         unsigned int pre_size = master->erasesize, post_size = 0;
  39         unsigned int root_offset = ROOT_OFFSET;
  40 
  41         int retries = 10;
  42         struct mtd_partition *ar7_parts;
  43 
  44         ar7_parts = kcalloc(AR7_PARTS, sizeof(*ar7_parts), GFP_KERNEL);
  45         if (!ar7_parts)
  46                 return -ENOMEM;
  47         ar7_parts[0].name = "loader";
  48         ar7_parts[0].offset = 0;
  49         ar7_parts[0].size = master->erasesize;
  50         ar7_parts[0].mask_flags = MTD_WRITEABLE;
  51 
  52         ar7_parts[1].name = "config";
  53         ar7_parts[1].offset = 0;
  54         ar7_parts[1].size = master->erasesize;
  55         ar7_parts[1].mask_flags = 0;
  56 
  57         do { /* Try 10 blocks starting from master->erasesize */
  58                 offset = pre_size;
  59                 mtd_read(master, offset, sizeof(header), &len,
  60                          (uint8_t *)&header);
  61                 if (!strncmp((char *)&header, "TIENV0.8", 8))
  62                         ar7_parts[1].offset = pre_size;
  63                 if (header.checksum == LOADER_MAGIC1)
  64                         break;
  65                 if (header.checksum == LOADER_MAGIC2)
  66                         break;
  67                 pre_size += master->erasesize;
  68         } while (retries--);
  69 
  70         pre_size = offset;
  71 
  72         if (!ar7_parts[1].offset) {
  73                 ar7_parts[1].offset = master->size - master->erasesize;
  74                 post_size = master->erasesize;
  75         }
  76 
  77         switch (header.checksum) {
  78         case LOADER_MAGIC1:
  79                 while (header.length) {
  80                         offset += sizeof(header) + header.length;
  81                         mtd_read(master, offset, sizeof(header), &len,
  82                                  (uint8_t *)&header);
  83                 }
  84                 root_offset = offset + sizeof(header) + 4;
  85                 break;
  86         case LOADER_MAGIC2:
  87                 while (header.length) {
  88                         offset += sizeof(header) + header.length;
  89                         mtd_read(master, offset, sizeof(header), &len,
  90                                  (uint8_t *)&header);
  91                 }
  92                 root_offset = offset + sizeof(header) + 4 + 0xff;
  93                 root_offset &= ~(uint32_t)0xff;
  94                 break;
  95         default:
  96                 printk(KERN_WARNING "Unknown magic: %08x\n", header.checksum);
  97                 break;
  98         }
  99 
 100         mtd_read(master, root_offset, sizeof(header), &len, (u8 *)&header);
 101         if (header.checksum != SQUASHFS_MAGIC) {
 102                 root_offset += master->erasesize - 1;
 103                 root_offset &= ~(master->erasesize - 1);
 104         }
 105 
 106         ar7_parts[2].name = "linux";
 107         ar7_parts[2].offset = pre_size;
 108         ar7_parts[2].size = master->size - pre_size - post_size;
 109         ar7_parts[2].mask_flags = 0;
 110 
 111         ar7_parts[3].name = "rootfs";
 112         ar7_parts[3].offset = root_offset;
 113         ar7_parts[3].size = master->size - root_offset - post_size;
 114         ar7_parts[3].mask_flags = 0;
 115 
 116         *pparts = ar7_parts;
 117         return AR7_PARTS;
 118 }
 119 
 120 static struct mtd_part_parser ar7_parser = {
 121         .parse_fn = create_mtd_partitions,
 122         .name = "ar7part",
 123 };
 124 module_mtd_part_parser(ar7_parser);
 125 
 126 MODULE_LICENSE("GPL");
 127 MODULE_AUTHOR(  "Felix Fietkau <nbd@openwrt.org>, "
 128                 "Eugene Konev <ejka@openwrt.org>");
 129 MODULE_DESCRIPTION("MTD partitioning for TI AR7");

/* [<][>][^][v][top][bottom][index][help] */