root/drivers/mtd/parsers/sharpslpart.c

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

DEFINITIONS

This source file includes following definitions.
  1. sharpsl_nand_check_ooblayout
  2. sharpsl_nand_read_oob
  3. sharpsl_nand_get_logical_num
  4. sharpsl_nand_init_ftl
  5. sharpsl_nand_cleanup_ftl
  6. sharpsl_nand_read_laddr
  7. sharpsl_nand_read_partinfo
  8. sharpsl_parse_mtd_partitions

   1 /*
   2  * sharpslpart.c - MTD partition parser for NAND flash using the SHARP FTL
   3  * for logical addressing, as used on the PXA models of the SHARP SL Series.
   4  *
   5  * Copyright (C) 2017 Andrea Adami <andrea.adami@gmail.com>
   6  *
   7  * Based on SHARP GPL 2.4 sources:
   8  *   http://support.ezaurus.com/developer/source/source_dl.asp
   9  *     drivers/mtd/nand/sharp_sl_logical.c
  10  *     linux/include/asm-arm/sharp_nand_logical.h
  11  *
  12  * Copyright (C) 2002 SHARP
  13  *
  14  * This program is free software; you can redistribute it and/or modify
  15  * it under the terms of the GNU General Public License as published by
  16  * the Free Software Foundation; either version 2 of the License, or
  17  * (at your option) any later version.
  18  *
  19  * This program is distributed in the hope that it will be useful,
  20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22  * GNU General Public License for more details.
  23  *
  24  */
  25 
  26 #include <linux/kernel.h>
  27 #include <linux/slab.h>
  28 #include <linux/module.h>
  29 #include <linux/types.h>
  30 #include <linux/bitops.h>
  31 #include <linux/sizes.h>
  32 #include <linux/mtd/mtd.h>
  33 #include <linux/mtd/partitions.h>
  34 
  35 /* oob structure */
  36 #define NAND_NOOB_LOGADDR_00            8
  37 #define NAND_NOOB_LOGADDR_01            9
  38 #define NAND_NOOB_LOGADDR_10            10
  39 #define NAND_NOOB_LOGADDR_11            11
  40 #define NAND_NOOB_LOGADDR_20            12
  41 #define NAND_NOOB_LOGADDR_21            13
  42 
  43 #define BLOCK_IS_RESERVED               0xffff
  44 #define BLOCK_UNMASK_COMPLEMENT         1
  45 
  46 /* factory defaults */
  47 #define SHARPSL_NAND_PARTS              3
  48 #define SHARPSL_FTL_PART_SIZE           (7 * SZ_1M)
  49 #define SHARPSL_PARTINFO1_LADDR         0x00060000
  50 #define SHARPSL_PARTINFO2_LADDR         0x00064000
  51 
  52 #define BOOT_MAGIC                      0x424f4f54
  53 #define FSRO_MAGIC                      0x4653524f
  54 #define FSRW_MAGIC                      0x46535257
  55 
  56 /**
  57  * struct sharpsl_ftl - Sharp FTL Logical Table
  58  * @logmax:             number of logical blocks
  59  * @log2phy:            the logical-to-physical table
  60  *
  61  * Structure containing the logical-to-physical translation table
  62  * used by the SHARP SL FTL.
  63  */
  64 struct sharpsl_ftl {
  65         unsigned int logmax;
  66         unsigned int *log2phy;
  67 };
  68 
  69 /* verify that the OOB bytes 8 to 15 are free and available for the FTL */
  70 static int sharpsl_nand_check_ooblayout(struct mtd_info *mtd)
  71 {
  72         u8 freebytes = 0;
  73         int section = 0;
  74 
  75         while (true) {
  76                 struct mtd_oob_region oobfree = { };
  77                 int ret, i;
  78 
  79                 ret = mtd_ooblayout_free(mtd, section++, &oobfree);
  80                 if (ret)
  81                         break;
  82 
  83                 if (!oobfree.length || oobfree.offset > 15 ||
  84                     (oobfree.offset + oobfree.length) < 8)
  85                         continue;
  86 
  87                 i = oobfree.offset >= 8 ? oobfree.offset : 8;
  88                 for (; i < oobfree.offset + oobfree.length && i < 16; i++)
  89                         freebytes |= BIT(i - 8);
  90 
  91                 if (freebytes == 0xff)
  92                         return 0;
  93         }
  94 
  95         return -ENOTSUPP;
  96 }
  97 
  98 static int sharpsl_nand_read_oob(struct mtd_info *mtd, loff_t offs, u8 *buf)
  99 {
 100         struct mtd_oob_ops ops = { };
 101         int ret;
 102 
 103         ops.mode = MTD_OPS_PLACE_OOB;
 104         ops.ooblen = mtd->oobsize;
 105         ops.oobbuf = buf;
 106 
 107         ret = mtd_read_oob(mtd, offs, &ops);
 108         if (ret != 0 || mtd->oobsize != ops.oobretlen)
 109                 return -1;
 110 
 111         return 0;
 112 }
 113 
 114 /*
 115  * The logical block number assigned to a physical block is stored in the OOB
 116  * of the first page, in 3 16-bit copies with the following layout:
 117  *
 118  * 01234567 89abcdef
 119  * -------- --------
 120  * ECC BB   xyxyxy
 121  *
 122  * When reading we check that the first two copies agree.
 123  * In case of error, matching is tried using the following pairs.
 124  * Reserved values 0xffff mean the block is kept for wear leveling.
 125  *
 126  * 01234567 89abcdef
 127  * -------- --------
 128  * ECC BB   xyxy    oob[8]==oob[10] && oob[9]==oob[11]   -> byte0=8   byte1=9
 129  * ECC BB     xyxy  oob[10]==oob[12] && oob[11]==oob[13] -> byte0=10  byte1=11
 130  * ECC BB   xy  xy  oob[12]==oob[8] && oob[13]==oob[9]   -> byte0=12  byte1=13
 131  */
 132 static int sharpsl_nand_get_logical_num(u8 *oob)
 133 {
 134         u16 us;
 135         int good0, good1;
 136 
 137         if (oob[NAND_NOOB_LOGADDR_00] == oob[NAND_NOOB_LOGADDR_10] &&
 138             oob[NAND_NOOB_LOGADDR_01] == oob[NAND_NOOB_LOGADDR_11]) {
 139                 good0 = NAND_NOOB_LOGADDR_00;
 140                 good1 = NAND_NOOB_LOGADDR_01;
 141         } else if (oob[NAND_NOOB_LOGADDR_10] == oob[NAND_NOOB_LOGADDR_20] &&
 142                    oob[NAND_NOOB_LOGADDR_11] == oob[NAND_NOOB_LOGADDR_21]) {
 143                 good0 = NAND_NOOB_LOGADDR_10;
 144                 good1 = NAND_NOOB_LOGADDR_11;
 145         } else if (oob[NAND_NOOB_LOGADDR_20] == oob[NAND_NOOB_LOGADDR_00] &&
 146                    oob[NAND_NOOB_LOGADDR_21] == oob[NAND_NOOB_LOGADDR_01]) {
 147                 good0 = NAND_NOOB_LOGADDR_20;
 148                 good1 = NAND_NOOB_LOGADDR_21;
 149         } else {
 150                 return -EINVAL;
 151         }
 152 
 153         us = oob[good0] | oob[good1] << 8;
 154 
 155         /* parity check */
 156         if (hweight16(us) & BLOCK_UNMASK_COMPLEMENT)
 157                 return -EINVAL;
 158 
 159         /* reserved */
 160         if (us == BLOCK_IS_RESERVED)
 161                 return BLOCK_IS_RESERVED;
 162 
 163         return (us >> 1) & GENMASK(9, 0);
 164 }
 165 
 166 static int sharpsl_nand_init_ftl(struct mtd_info *mtd, struct sharpsl_ftl *ftl)
 167 {
 168         unsigned int block_num, phymax;
 169         int i, ret, log_num;
 170         loff_t block_adr;
 171         u8 *oob;
 172 
 173         oob = kzalloc(mtd->oobsize, GFP_KERNEL);
 174         if (!oob)
 175                 return -ENOMEM;
 176 
 177         phymax = mtd_div_by_eb(SHARPSL_FTL_PART_SIZE, mtd);
 178 
 179         /* FTL reserves 5% of the blocks + 1 spare  */
 180         ftl->logmax = ((phymax * 95) / 100) - 1;
 181 
 182         ftl->log2phy = kmalloc_array(ftl->logmax, sizeof(*ftl->log2phy),
 183                                      GFP_KERNEL);
 184         if (!ftl->log2phy) {
 185                 ret = -ENOMEM;
 186                 goto exit;
 187         }
 188 
 189         /* initialize ftl->log2phy */
 190         for (i = 0; i < ftl->logmax; i++)
 191                 ftl->log2phy[i] = UINT_MAX;
 192 
 193         /* create physical-logical table */
 194         for (block_num = 0; block_num < phymax; block_num++) {
 195                 block_adr = (loff_t)block_num * mtd->erasesize;
 196 
 197                 if (mtd_block_isbad(mtd, block_adr))
 198                         continue;
 199 
 200                 if (sharpsl_nand_read_oob(mtd, block_adr, oob))
 201                         continue;
 202 
 203                 /* get logical block */
 204                 log_num = sharpsl_nand_get_logical_num(oob);
 205 
 206                 /* cut-off errors and skip the out-of-range values */
 207                 if (log_num > 0 && log_num < ftl->logmax) {
 208                         if (ftl->log2phy[log_num] == UINT_MAX)
 209                                 ftl->log2phy[log_num] = block_num;
 210                 }
 211         }
 212 
 213         pr_info("Sharp SL FTL: %d blocks used (%d logical, %d reserved)\n",
 214                 phymax, ftl->logmax, phymax - ftl->logmax);
 215 
 216         ret = 0;
 217 exit:
 218         kfree(oob);
 219         return ret;
 220 }
 221 
 222 static void sharpsl_nand_cleanup_ftl(struct sharpsl_ftl *ftl)
 223 {
 224         kfree(ftl->log2phy);
 225 }
 226 
 227 static int sharpsl_nand_read_laddr(struct mtd_info *mtd,
 228                                    loff_t from,
 229                                    size_t len,
 230                                    void *buf,
 231                                    struct sharpsl_ftl *ftl)
 232 {
 233         unsigned int log_num, final_log_num;
 234         unsigned int block_num;
 235         loff_t block_adr;
 236         loff_t block_ofs;
 237         size_t retlen;
 238         int err;
 239 
 240         log_num = mtd_div_by_eb((u32)from, mtd);
 241         final_log_num = mtd_div_by_eb(((u32)from + len - 1), mtd);
 242 
 243         if (len <= 0 || log_num >= ftl->logmax || final_log_num > log_num)
 244                 return -EINVAL;
 245 
 246         block_num = ftl->log2phy[log_num];
 247         block_adr = (loff_t)block_num * mtd->erasesize;
 248         block_ofs = mtd_mod_by_eb((u32)from, mtd);
 249 
 250         err = mtd_read(mtd, block_adr + block_ofs, len, &retlen, buf);
 251         /* Ignore corrected ECC errors */
 252         if (mtd_is_bitflip(err))
 253                 err = 0;
 254 
 255         if (!err && retlen != len)
 256                 err = -EIO;
 257 
 258         if (err)
 259                 pr_err("sharpslpart: error, read failed at %#llx\n",
 260                        block_adr + block_ofs);
 261 
 262         return err;
 263 }
 264 
 265 /*
 266  * MTD Partition Parser
 267  *
 268  * Sample values read from SL-C860
 269  *
 270  * # cat /proc/mtd
 271  * dev:    size   erasesize  name
 272  * mtd0: 006d0000 00020000 "Filesystem"
 273  * mtd1: 00700000 00004000 "smf"
 274  * mtd2: 03500000 00004000 "root"
 275  * mtd3: 04400000 00004000 "home"
 276  *
 277  * PARTITIONINFO1
 278  * 0x00060000: 00 00 00 00 00 00 70 00 42 4f 4f 54 00 00 00 00  ......p.BOOT....
 279  * 0x00060010: 00 00 70 00 00 00 c0 03 46 53 52 4f 00 00 00 00  ..p.....FSRO....
 280  * 0x00060020: 00 00 c0 03 00 00 00 04 46 53 52 57 00 00 00 00  ........FSRW....
 281  */
 282 struct sharpsl_nand_partinfo {
 283         __le32 start;
 284         __le32 end;
 285         __be32 magic;
 286         u32 reserved;
 287 };
 288 
 289 static int sharpsl_nand_read_partinfo(struct mtd_info *master,
 290                                       loff_t from,
 291                                       size_t len,
 292                                       struct sharpsl_nand_partinfo *buf,
 293                                       struct sharpsl_ftl *ftl)
 294 {
 295         int ret;
 296 
 297         ret = sharpsl_nand_read_laddr(master, from, len, buf, ftl);
 298         if (ret)
 299                 return ret;
 300 
 301         /* check for magics */
 302         if (be32_to_cpu(buf[0].magic) != BOOT_MAGIC ||
 303             be32_to_cpu(buf[1].magic) != FSRO_MAGIC ||
 304             be32_to_cpu(buf[2].magic) != FSRW_MAGIC) {
 305                 pr_err("sharpslpart: magic values mismatch\n");
 306                 return -EINVAL;
 307         }
 308 
 309         /* fixup for hardcoded value 64 MiB (for older models) */
 310         buf[2].end = cpu_to_le32(master->size);
 311 
 312         /* extra sanity check */
 313         if (le32_to_cpu(buf[0].end) <= le32_to_cpu(buf[0].start) ||
 314             le32_to_cpu(buf[1].start) < le32_to_cpu(buf[0].end) ||
 315             le32_to_cpu(buf[1].end) <= le32_to_cpu(buf[1].start) ||
 316             le32_to_cpu(buf[2].start) < le32_to_cpu(buf[1].end) ||
 317             le32_to_cpu(buf[2].end) <= le32_to_cpu(buf[2].start)) {
 318                 pr_err("sharpslpart: partition sizes mismatch\n");
 319                 return -EINVAL;
 320         }
 321 
 322         return 0;
 323 }
 324 
 325 static int sharpsl_parse_mtd_partitions(struct mtd_info *master,
 326                                         const struct mtd_partition **pparts,
 327                                         struct mtd_part_parser_data *data)
 328 {
 329         struct sharpsl_ftl ftl;
 330         struct sharpsl_nand_partinfo buf[SHARPSL_NAND_PARTS];
 331         struct mtd_partition *sharpsl_nand_parts;
 332         int err;
 333 
 334         /* check that OOB bytes 8 to 15 used by the FTL are actually free */
 335         err = sharpsl_nand_check_ooblayout(master);
 336         if (err)
 337                 return err;
 338 
 339         /* init logical mgmt (FTL) */
 340         err = sharpsl_nand_init_ftl(master, &ftl);
 341         if (err)
 342                 return err;
 343 
 344         /* read and validate first partition table */
 345         pr_info("sharpslpart: try reading first partition table\n");
 346         err = sharpsl_nand_read_partinfo(master,
 347                                          SHARPSL_PARTINFO1_LADDR,
 348                                          sizeof(buf), buf, &ftl);
 349         if (err) {
 350                 /* fallback: read second partition table */
 351                 pr_warn("sharpslpart: first partition table is invalid, retry using the second\n");
 352                 err = sharpsl_nand_read_partinfo(master,
 353                                                  SHARPSL_PARTINFO2_LADDR,
 354                                                  sizeof(buf), buf, &ftl);
 355         }
 356 
 357         /* cleanup logical mgmt (FTL) */
 358         sharpsl_nand_cleanup_ftl(&ftl);
 359 
 360         if (err) {
 361                 pr_err("sharpslpart: both partition tables are invalid\n");
 362                 return err;
 363         }
 364 
 365         sharpsl_nand_parts = kcalloc(SHARPSL_NAND_PARTS,
 366                                      sizeof(*sharpsl_nand_parts),
 367                                      GFP_KERNEL);
 368         if (!sharpsl_nand_parts)
 369                 return -ENOMEM;
 370 
 371         /* original names */
 372         sharpsl_nand_parts[0].name = "smf";
 373         sharpsl_nand_parts[0].offset = le32_to_cpu(buf[0].start);
 374         sharpsl_nand_parts[0].size = le32_to_cpu(buf[0].end) -
 375                                      le32_to_cpu(buf[0].start);
 376 
 377         sharpsl_nand_parts[1].name = "root";
 378         sharpsl_nand_parts[1].offset = le32_to_cpu(buf[1].start);
 379         sharpsl_nand_parts[1].size = le32_to_cpu(buf[1].end) -
 380                                      le32_to_cpu(buf[1].start);
 381 
 382         sharpsl_nand_parts[2].name = "home";
 383         sharpsl_nand_parts[2].offset = le32_to_cpu(buf[2].start);
 384         sharpsl_nand_parts[2].size = le32_to_cpu(buf[2].end) -
 385                                      le32_to_cpu(buf[2].start);
 386 
 387         *pparts = sharpsl_nand_parts;
 388         return SHARPSL_NAND_PARTS;
 389 }
 390 
 391 static struct mtd_part_parser sharpsl_mtd_parser = {
 392         .parse_fn = sharpsl_parse_mtd_partitions,
 393         .name = "sharpslpart",
 394 };
 395 module_mtd_part_parser(sharpsl_mtd_parser);
 396 
 397 MODULE_LICENSE("GPL");
 398 MODULE_AUTHOR("Andrea Adami <andrea.adami@gmail.com>");
 399 MODULE_DESCRIPTION("MTD partitioning for NAND flash on Sharp SL Series");

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