diff --git a/nand-image-builder.c b/nand-image-builder.c index 645d1cc..0ca2d14 100644 --- a/nand-image-builder.c +++ b/nand-image-builder.c @@ -14,55 +14,22 @@ * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * + * For the BCH implementation: + * * Copyright © 2011 Parrot S.A. * * Author: Ivan Djelic * - * Description: + * See also: + * http://lxr.free-electrons.com/source/lib/bch.c * - * This library provides runtime configurable encoding/decoding of binary - * Bose-Chaudhuri-Hocquenghem (BCH) codes. + * For the randomizer and image builder implementation: * - * Call init_bch to get a pointer to a newly allocated bch_control structure for - * the given m (Galois field order), t (error correction capability) and - * (optional) primitive polynomial parameters. + * Copyright © 2016 NextThing Co. + * Copyright © 2016 Free Electrons * - * Call encode_bch to compute and store ecc parity bytes to a given buffer. - * Call decode_bch to detect and locate errors in received data. + * Author: Boris Brezillon * - * On systems supporting hw BCH features, intermediate results may be provided - * to decode_bch in order to skip certain steps. See decode_bch() documentation - * for details. - * - * Option CONFIG_BCH_CONST_PARAMS can be used to force fixed values of - * parameters m and t; thus allowing extra compiler optimizations and providing - * better (up to 2x) encoding performance. Using this option makes sense when - * (m,t) are fixed and known in advance, e.g. when using BCH error correction - * on a particular NAND flash device. - * - * Algorithmic details: - * - * Encoding is performed by processing 32 input bits in parallel, using 4 - * remainder lookup tables. - * - * The final stage of decoding involves the following internal steps: - * a. Syndrome computation - * b. Error locator polynomial computation using Berlekamp-Massey algorithm - * c. Error locator root finding (by far the most expensive step) - * - * In this implementation, step c is not performed using the usual Chien search. - * Instead, an alternative approach described in [1] is used. It consists in - * factoring the error locator polynomial using the Berlekamp Trace algorithm - * (BTA) down to a certain degree (4), after which ad hoc low-degree polynomial - * solving techniques [2] are used. The resulting algorithm, called BTZ, yields - * much better performance than Chien search for usual (m,t) values (typically - * m >= 13, t < 32, see [1]). - * - * [1] B. Biswas, V. Herbert. Efficient root finding of polynomials over fields - * of characteristic 2, in: Western European Workshop on Research in Cryptology - * - WEWoRC 2009, Graz, Austria, LNCS, Springer, July 2009, to appear. - * [2] [Zin96] V.A. Zinoviev. On the solution of equations of degree 10 over - * finite fields GF(2^q). In Rapport de recherche INRIA no 2829, 1996. */ #include @@ -950,21 +917,51 @@ static void display_help(int status) { fprintf(status == EXIT_SUCCESS ? stdout : stderr, "Usage: sunxi-nand-image-builder [OPTIONS] source-image output-image\n" + "\n" "Creates a raw NAND image that can be read by the sunxi NAND controller.\n" "\n" - "-h --help Display this help and exit\n" - "-c / --ecc=/ ECC config\n" - " Valid strengths: 16, 24, 28, 32, 40, 48, 56, 60 and 64\n" - " Valid steps: 512 and 1024\n" - "-p --page-size= Page size\n" - "-o --oob-size= OOB size\n" - "-u --usable-page-size= Usable page size. Only needed for boot0 mode\n" - "-e --eraseblock-size= Erase block size\n" - "-b --boot0 Build a boot0 image.\n" - "-s --scramble Scramble data\n" - "-a --address Where the image will be programmed.\n" - " This option is only required for non boot0 images that are meant to be programmed at a non eraseblock aligned offset.\n" - "\n"); + "-h --help Display this help and exit\n" + "-c / --ecc=/ ECC config (strength/step-size)\n" + "-p --page= Page size\n" + "-o --oob= OOB size\n" + "-u --usable= Usable page size\n" + "-e --eraseblock= Erase block size\n" + "-b --boot0 Build a boot0 image.\n" + "-s --scramble Scramble data\n" + "-a --address= Where the image will be programmed.\n" + "\n" + "Notes:\n" + "All the information you need to pass to this tool should be part of\n" + "the NAND datasheet.\n" + "\n" + "The NAND controller only supports the following ECC configs\n" + " Valid ECC strengths: 16, 24, 28, 32, 40, 48, 56, 60 and 64\n" + " Valid ECC step size: 512 and 1024\n" + "\n" + "If you are building a boot0 image, you'll have specify extra options.\n" + "These options should be chosen based on the layouts described here:\n" + " http://linux-sunxi.org/NAND#More_information_on_BROM_NAND\n" + "\n" + " --usable should be assigned the 'Hardware page' value\n" + " --ecc should be assigned the 'ECC capacity'/'ECC page' values\n" + " --usable should be smaller than --page\n" + "\n" + "The --address option is only required for non-boot0 images that are \n" + "meant to be programmed at a non eraseblock aligned offset.\n" + "\n" + "Examples:\n" + " The H27UCG8T2BTR-BC NAND exposes\n" + " * 16k pages\n" + " * 1280 OOB bytes per page\n" + " * 4M eraseblocks\n" + " * requires data scrambling\n" + " * expects a minimum ECC of 40bits/1024bytes\n" + "\n" + " A normal image can be generated with\n" + " sunxi-nand-image-builder -p 16384 -o 1280 -e 0x400000 -s -c 40/1024\n" + " A boot0 image can be generated with\n" + " sunxi-nand-image-builder -p 16384 -o 1280 -e 0x400000 -s -b -u 4096 -c 64/1024\n" + ); exit(status); } @@ -974,20 +971,37 @@ static int check_image_info(struct image_info *info) int eccbytes, eccsteps; unsigned i; - if (!info->page_size || !info->oob_size || !info->eraseblock_size || - !info->usable_page_size) + if (!info->page_size) { + fprintf(stderr, "--page is missing\n"); return -EINVAL; + } - if (info->ecc_step_size != 512 && info->ecc_step_size != 1024) + if (!info->page_size) { + fprintf(stderr, "--oob is missing\n"); return -EINVAL; + } + + if (!info->eraseblock_size) { + fprintf(stderr, "--eraseblock is missing\n"); + return -EINVAL; + } + + if (info->ecc_step_size != 512 && info->ecc_step_size != 1024) { + fprintf(stderr, "Invalid ECC step argument: %d\n", + info->ecc_step_size); + return -EINVAL; + } for (i = 0; i < ARRAY_SIZE(valid_ecc_strengths); i++) { if (valid_ecc_strengths[i] == info->ecc_strength) break; } - if (i == ARRAY_SIZE(valid_ecc_strengths)) + if (i == ARRAY_SIZE(valid_ecc_strengths)) { + fprintf(stderr, "Invalid ECC strength argument: %d\n", + info->ecc_strength); return -EINVAL; + } eccbytes = DIV_ROUND_UP(info->ecc_strength * 14, 8); if (eccbytes % 2) @@ -997,8 +1011,11 @@ static int check_image_info(struct image_info *info) eccsteps = info->usable_page_size / info->ecc_step_size; if (info->page_size + info->oob_size < - info->usable_page_size + (eccsteps * (eccbytes))) + info->usable_page_size + (eccsteps * eccbytes)) { + fprintf(stderr, + "ECC bytes do not fit in the NAND page, choose a weaker ECC\n"); return -EINVAL; + } return 0; } @@ -1015,19 +1032,19 @@ int main(int argc, char **argv) int option_index = 0; char *endptr = NULL; static const struct option long_options[] = { - {"help", no_argument, 0, 0}, + {"help", no_argument, 0, 'h'}, {"ecc", required_argument, 0, 'c'}, - {"page-size", required_argument, 0, 'p'}, - {"oob-size", required_argument, 0, 'o'}, - {"usable-page-size", required_argument, 0, 'u'}, - {"eraseblock-size", required_argument, 0, 'e'}, + {"page", required_argument, 0, 'p'}, + {"oob", required_argument, 0, 'o'}, + {"usable", required_argument, 0, 'u'}, + {"eraseblock", required_argument, 0, 'e'}, {"boot0", no_argument, 0, 'b'}, {"scramble", no_argument, 0, 's'}, {"address", required_argument, 0, 'a'}, {0, 0, 0, 0}, }; - int c = getopt_long(argc, argv, "c:p:o:u:e:ba:s", + int c = getopt_long(argc, argv, "c:p:o:u:e:ba:sh", long_options, &option_index); if (c == EOF) break;