11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================== 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drivers/mtd/afs.c: ARM Flash Layout/Partitioning 497894cda5773e59bd13e87b72077751099419a9fThomas Gleixner 5a1452a3771c4eb85bd779790b040efdc36f4274eDavid Woodhouse Copyright © 2000 ARM Limited 697894cda5773e59bd13e87b72077751099419a9fThomas Gleixner 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is free software; you can redistribute it and/or modify 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it under the terms of the GNU General Public License as published by 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the Free Software Foundation; either version 2 of the License, or 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (at your option) any later version. 1197894cda5773e59bd13e87b72077751099419a9fThomas Gleixner 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is distributed in the hope that it will be useful, 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds but WITHOUT ANY WARRANTY; without even the implied warranty of 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GNU General Public License for more details. 1697894cda5773e59bd13e87b72077751099419a9fThomas Gleixner 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds You should have received a copy of the GNU General Public License 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds along with this program; if not, write to the Free Software 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 2097894cda5773e59bd13e87b72077751099419a9fThomas Gleixner 2197894cda5773e59bd13e87b72077751099419a9fThomas Gleixner This is access code for flashes using ARM's flash partitioning 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds standards. 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds======================================================================*/ 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/mtd.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/map.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/partitions.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct footer_struct { 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 image_info_base; /* Address of first word of ImageFooter */ 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 image_start; /* Start of area reserved by this footer */ 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 signature; /* 'Magic' number proves it's a footer */ 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 type; /* Area type: ARM Image, SIB, customer */ 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 checksum; /* Just this structure */ 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct image_info_struct { 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 bootFlags; /* Boot flags, compression etc. */ 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 imageNumber; /* Unique number, selects for boot etc. */ 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 loadAddress; /* Address program should be loaded to */ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 length; /* Actual size of image */ 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 address; /* Image is executed from here */ 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char name[16]; /* Null terminated */ 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 headerBase; /* Flash Address of any stripped header */ 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 header_length; /* Length of header in memory */ 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 headerType; /* AIF, RLF, s-record etc. */ 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 checksum; /* Image checksum (inc. this struct) */ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 word_sum(void *words, int num) 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 *p = words; 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 sum = 0; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (num--) 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sum += *p++; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sum; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsafs_read_footer(struct mtd_info *mtd, u_int *img_start, u_int *iis_start, 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int off, u_int mask) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct footer_struct fs; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int ptr = off + mtd->erasesize - sizeof(fs); 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t sz; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 78329ad399a9b3adf52c90637b21ca029fcf7f8795Artem Bityutskiy ret = mtd_read(mtd, ptr, sizeof(fs), &sz, (u_char *)&fs); 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret >= 0 && sz != sizeof(fs)) 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EINVAL; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) { 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n", 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr, ret); 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 1; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Does it contain the magic number? 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fs.signature != 0xa0ffff9f) 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check the checksum. 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (word_sum(&fs, sizeof(fs) / sizeof(u32)) != 0xffffffff) 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Don't touch the SIB. 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fs.type == 2) 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *iis_start = fs.image_info_base & mask; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *img_start = fs.image_start & mask; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check the image info base. This can not 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * be located after the footer structure. 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*iis_start >= ptr) 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check the start of this image. The image 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data can not be located after this block. 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*img_start > off) 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsafs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr) 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t sz; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret, i; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(iis, 0, sizeof(*iis)); 135329ad399a9b3adf52c90637b21ca029fcf7f8795Artem Bityutskiy ret = mtd_read(mtd, ptr, sizeof(*iis), &sz, (u_char *)iis); 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sz != sizeof(*iis)) { 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EINVAL; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Validate the name - it must be NUL terminated. 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < sizeof(iis->name); i++) 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (iis->name[i] == '\0') 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i < sizeof(iis->name)) 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 1; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed: 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n", 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr, ret); 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16497894cda5773e59bd13e87b72077751099419a9fThomas Gleixnerstatic int parse_afs_partitions(struct mtd_info *mtd, 165c7975330154af17aecc167b33ca866b6b3d98918Dmitry Eremin-Solenikov struct mtd_partition **pparts, 166c7975330154af17aecc167b33ca866b6b3d98918Dmitry Eremin-Solenikov struct mtd_part_parser_data *data) 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mtd_partition *parts; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int mask, off, idx, sz; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *str; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is the address mask; we use this to mask off out of 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * range address bits. 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = mtd->size - 1; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * First, calculate the size of the array we need for the 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * partition information. We include in this the size of 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the strings. 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = off = sz = 0; off < mtd->size; off += mtd->erasesize) { 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct image_info_struct iis; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int iis_ptr, img_ptr; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask); 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret == 0) 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = afs_read_iis(mtd, &iis, iis_ptr); 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret == 0) 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sz += sizeof(struct mtd_partition); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sz += strlen(iis.name) + 1; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds idx += 1; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sz) 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20895b93a0cd46682c6d9e8eea803fda510cb6b863aBurman Yan parts = kzalloc(sz, GFP_KERNEL); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!parts) 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds str = (char *)(parts + idx); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Identify the partitions 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = off = 0; off < mtd->size; off += mtd->erasesize) { 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct image_info_struct iis; 219747aead34de65c25765da79825ce2c08d8257b10Catalin Marinas u_int iis_ptr, img_ptr; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read the footer. */ 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask); 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret == 0) 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read the image info block */ 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = afs_read_iis(mtd, &iis, iis_ptr); 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret == 0) 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(str, iis.name); 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds parts[idx].name = str; 238747aead34de65c25765da79825ce2c08d8257b10Catalin Marinas parts[idx].size = (iis.length + mtd->erasesize - 1) & ~(mtd->erasesize - 1); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds parts[idx].offset = img_ptr; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds parts[idx].mask_flags = 0; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2420ffd24fc7f82a0b594250e5f221340be4c322cdaRussell King printk(" mtd%d: at 0x%08x, %5lluKiB, %8u, %s\n", 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds idx, img_ptr, parts[idx].size / 1024, 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iis.imageNumber, str); 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds idx += 1; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds str = str + strlen(iis.name) + 1; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!idx) { 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(parts); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds parts = NULL; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *pparts = parts; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return idx ? idx : ret; 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mtd_part_parser afs_parser = { 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .parse_fn = parse_afs_partitions, 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "afs", 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init afs_parser_init(void) 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2676e14a61d412eb87ef7bdcec8b08a95bead771a78Axel Lin register_mtd_parser(&afs_parser); 2686e14a61d412eb87ef7bdcec8b08a95bead771a78Axel Lin return 0; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit afs_parser_exit(void) 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds deregister_mtd_parser(&afs_parser); 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(afs_parser_init); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(afs_parser_exit); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("ARM Ltd"); 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("ARM Firmware Suite partition parser"); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 283