1/*====================================================================== 2 3 drivers/mtd/afs.c: ARM Flash Layout/Partitioning 4 5 Copyright (C) 2000 ARM Limited 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 21 This is access code for flashes using ARM's flash partitioning 22 standards. 23 24 $Id: afs.c,v 1.1.1.1 2008/10/15 03:26:35 james26_jang Exp $ 25 26======================================================================*/ 27 28#include <linux/module.h> 29#include <linux/types.h> 30#include <linux/kernel.h> 31#include <linux/slab.h> 32#include <linux/string.h> 33#include <linux/init.h> 34 35#include <linux/mtd/mtd.h> 36#include <linux/mtd/map.h> 37#include <linux/mtd/partitions.h> 38 39struct footer_struct { 40 u32 image_info_base; /* Address of first word of ImageFooter */ 41 u32 image_start; /* Start of area reserved by this footer */ 42 u32 signature; /* 'Magic' number proves it's a footer */ 43 u32 type; /* Area type: ARM Image, SIB, customer */ 44 u32 checksum; /* Just this structure */ 45}; 46 47struct image_info_struct { 48 u32 bootFlags; /* Boot flags, compression etc. */ 49 u32 imageNumber; /* Unique number, selects for boot etc. */ 50 u32 loadAddress; /* Address program should be loaded to */ 51 u32 length; /* Actual size of image */ 52 u32 address; /* Image is executed from here */ 53 char name[16]; /* Null terminated */ 54 u32 headerBase; /* Flash Address of any stripped header */ 55 u32 header_length; /* Length of header in memory */ 56 u32 headerType; /* AIF, RLF, s-record etc. */ 57 u32 checksum; /* Image checksum (inc. this struct) */ 58}; 59 60static int 61afs_read_footer(struct mtd_info *mtd, u_int *img_start, u_int *iis_start, 62 u_int off, u_int mask) 63{ 64 struct footer_struct fs; 65 u_int ptr = off + mtd->erasesize - sizeof(fs); 66 size_t sz; 67 int ret; 68 69 ret = mtd->read(mtd, ptr, sizeof(fs), &sz, (u_char *) &fs); 70 if (ret >= 0 && sz != sizeof(fs)) 71 ret = -EINVAL; 72 73 if (ret < 0) { 74 printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n", 75 ptr, ret); 76 return ret; 77 } 78 79 /* 80 * Does it contain the magic number? 81 */ 82 if (fs.signature != 0xa0ffff9f) 83 ret = 1; 84 85 /* 86 * Don't touch the SIB. 87 */ 88 if (fs.type == 2) 89 ret = 1; 90 91 *iis_start = fs.image_info_base & mask; 92 *img_start = fs.image_start & mask; 93 94 /* 95 * Check the image info base. This can not 96 * be located after the footer structure. 97 */ 98 if (*iis_start >= ptr) 99 ret = 1; 100 101 /* 102 * Check the start of this image. The image 103 * data can not be located after this block. 104 */ 105 if (*img_start > off) 106 ret = 1; 107 108 return ret; 109} 110 111static int 112afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr) 113{ 114 size_t sz; 115 int ret; 116 117 memset(iis, 0, sizeof(*iis)); 118 ret = mtd->read(mtd, ptr, sizeof(*iis), &sz, (u_char *) iis); 119 if (ret >= 0 && sz != sizeof(*iis)) 120 ret = -EINVAL; 121 if (ret < 0) 122 printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n", 123 ptr, ret); 124 125 return ret; 126} 127 128int parse_afs_partitions(struct mtd_info *mtd, struct mtd_partition **pparts) 129{ 130 struct mtd_partition *parts; 131 u_int mask, off, idx, sz; 132 int ret = 0; 133 char *str; 134 135 /* 136 * This is the address mask; we use this to mask off out of 137 * range address bits. 138 */ 139 mask = mtd->size - 1; 140 141 /* 142 * First, calculate the size of the array we need for the 143 * partition information. We include in this the size of 144 * the strings. 145 */ 146 for (idx = off = sz = 0; off < mtd->size; off += mtd->erasesize) { 147 struct image_info_struct iis; 148 u_int iis_ptr, img_ptr; 149 150 ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask); 151 if (ret < 0) 152 break; 153 if (ret == 1) 154 continue; 155 156 ret = afs_read_iis(mtd, &iis, iis_ptr); 157 if (ret < 0) 158 break; 159 160 sz += sizeof(struct mtd_partition); 161 sz += strlen(iis.name) + 1; 162 idx += 1; 163 } 164 165 if (!sz) 166 return ret; 167 168 parts = kmalloc(sz, GFP_KERNEL); 169 if (!parts) 170 return -ENOMEM; 171 172 str = (char *)(parts + idx); 173 174 /* 175 * Identify the partitions 176 */ 177 for (idx = off = 0; off < mtd->size; off += mtd->erasesize) { 178 struct image_info_struct iis; 179 u_int iis_ptr, img_ptr, size; 180 181 /* Read the footer. */ 182 ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask); 183 if (ret < 0) 184 break; 185 if (ret == 1) 186 continue; 187 188 /* Read the image info block */ 189 ret = afs_read_iis(mtd, &iis, iis_ptr); 190 if (ret < 0) 191 break; 192 193 strcpy(str, iis.name); 194 size = mtd->erasesize + off - img_ptr; 195 196 /* 197 * In order to support JFFS2 partitions on this layout, 198 * we must lie to MTD about the real size of JFFS2 199 * partitions; this ensures that the AFS flash footer 200 * won't be erased by JFFS2. Please ensure that your 201 * JFFS2 partitions are given image numbers between 202 * 1000 and 2000 inclusive. 203 */ 204 if (iis.imageNumber >= 1000 && iis.imageNumber < 2000) 205 size -= mtd->erasesize; 206 207 parts[idx].name = str; 208 parts[idx].size = size; 209 parts[idx].offset = img_ptr; 210 parts[idx].mask_flags = 0; 211 212 printk(" mtd%d: at 0x%08x, %5dKB, %8u, %s\n", 213 idx, img_ptr, parts[idx].size / 1024, 214 iis.imageNumber, str); 215 216 idx += 1; 217 str = str + strlen(iis.name) + 1; 218 } 219 220 if (!idx) { 221 kfree(parts); 222 parts = NULL; 223 } 224 225 *pparts = parts; 226 return idx ? idx : ret; 227} 228 229EXPORT_SYMBOL(parse_afs_partitions); 230 231MODULE_AUTHOR("ARM Ltd"); 232MODULE_DESCRIPTION("ARM Firmware Suite partition parser"); 233MODULE_LICENSE("GPL"); 234