busybox/miscutils/flash_eraseall.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/* eraseall.c -- erase the whole of a MTD device
   3 *
   4 * Ported to busybox from mtd-utils.
   5 *
   6 * Copyright (C) 2000 Arcom Control System Ltd
   7 *
   8 * Renamed to flash_eraseall.c
   9 *
  10 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  11 */
  12
  13#include "libbb.h"
  14#include <mtd/mtd-user.h>
  15#include <mtd/jffs2-user.h>
  16
  17#define OPTION_J        (1 << 0)
  18#define OPTION_Q        (1 << 1)
  19#define IS_NAND         (1 << 2)
  20#define BBTEST          (1 << 3)
  21
  22struct globals {
  23        /* This is used in the cpu_to_je/je_to_cpu macros in jffs2_user.h */
  24        int tgt_endian;
  25};
  26#define G (*(struct globals*)&bb_common_bufsiz1)
  27#define target_endian   (G.tgt_endian)
  28#define INIT_G() do { \
  29        target_endian = __BYTE_ORDER; \
  30} while (0)
  31
  32static uint32_t crc32(uint32_t val, const void *ss, int len,
  33                uint32_t *crc32_table)
  34{
  35        const unsigned char *s = ss;
  36        while (--len >= 0)
  37                val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8);
  38        return val;
  39}
  40
  41static void show_progress(mtd_info_t *meminfo, erase_info_t *erase)
  42{
  43        printf("\rErasing %d Kibyte @ %x -- %2llu %% complete.",
  44                (unsigned)meminfo->erasesize / 1024, erase->start,
  45                (unsigned long long) erase->start * 100 / meminfo->size);
  46        fflush(stdout);
  47}
  48
  49int flash_eraseall_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  50int flash_eraseall_main(int argc UNUSED_PARAM, char **argv)
  51{
  52        struct jffs2_unknown_node cleanmarker;
  53        mtd_info_t meminfo;
  54        int fd, clmpos, clmlen;
  55        erase_info_t erase;
  56        struct stat st;
  57        unsigned int flags;
  58        char *mtd_name;
  59
  60        INIT_G();
  61        opt_complementary = "=1";
  62        flags = BBTEST | getopt32(argv, "jq");
  63
  64        mtd_name = argv[optind];
  65        xstat(mtd_name, &st);
  66        if (!S_ISCHR(st.st_mode))
  67                bb_error_msg_and_die("%s: not a char device", mtd_name);
  68
  69        fd = xopen(mtd_name, O_RDWR);
  70
  71        xioctl(fd, MEMGETINFO, &meminfo);
  72        erase.length = meminfo.erasesize;
  73        if (meminfo.type == MTD_NANDFLASH)
  74                flags |= IS_NAND;
  75
  76        clmpos = 0;
  77        clmlen = 8;
  78        if (flags & OPTION_J) {
  79                uint32_t *crc32_table;
  80
  81                crc32_table = crc32_filltable(NULL, 0);
  82
  83                cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
  84                cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
  85                if (!(flags & IS_NAND))
  86                        cleanmarker.totlen = cpu_to_je32(sizeof(struct jffs2_unknown_node));
  87                else {
  88                        struct nand_oobinfo oobinfo;
  89
  90                        xioctl(fd, MEMGETOOBSEL, &oobinfo);
  91
  92                        /* Check for autoplacement */
  93                        if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
  94                                /* Get the position of the free bytes */
  95                                clmpos = oobinfo.oobfree[0][0];
  96                                clmlen = oobinfo.oobfree[0][1];
  97                                if (clmlen > 8)
  98                                        clmlen = 8;
  99                                if (clmlen == 0)
 100                                        bb_error_msg_and_die("Autoplacement selected and no empty space in oob");
 101                        } else {
 102                                /* Legacy mode */
 103                                switch (meminfo.oobsize) {
 104                                case 8:
 105                                        clmpos = 6;
 106                                        clmlen = 2;
 107                                        break;
 108                                case 16:
 109                                        clmpos = 8;
 110                                        /*clmlen = 8;*/
 111                                        break;
 112                                case 64:
 113                                        clmpos = 16;
 114                                        /*clmlen = 8;*/
 115                                        break;
 116                                }
 117                        }
 118                        cleanmarker.totlen = cpu_to_je32(8);
 119                }
 120
 121                cleanmarker.hdr_crc = cpu_to_je32(crc32(0, &cleanmarker, sizeof(struct jffs2_unknown_node) - 4,
 122                                        crc32_table));
 123        }
 124
 125        /* Don't want to destroy progress indicator by bb_error_msg's */
 126        applet_name = xasprintf("\n%s: %s", applet_name, mtd_name);
 127
 128        for (erase.start = 0; erase.start < meminfo.size;
 129             erase.start += meminfo.erasesize) {
 130                if (flags & BBTEST) {
 131                        int ret;
 132                        loff_t offset = erase.start;
 133
 134                        ret = ioctl(fd, MEMGETBADBLOCK, &offset);
 135                        if (ret > 0) {
 136                                if (!(flags & OPTION_Q))
 137                                        bb_info_msg("\nSkipping bad block at 0x%08x", erase.start);
 138                                continue;
 139                        }
 140                        if (ret < 0) {
 141                                /* Black block table is not available on certain flash
 142                                 * types e.g. NOR
 143                                 */
 144                                if (errno == EOPNOTSUPP) {
 145                                        flags &= ~BBTEST;
 146                                        if (flags & IS_NAND)
 147                                                bb_error_msg_and_die("bad block check not available");
 148                                } else {
 149                                        bb_perror_msg_and_die("MEMGETBADBLOCK error");
 150                                }
 151                        }
 152                }
 153
 154                if (!(flags & OPTION_Q))
 155                        show_progress(&meminfo, &erase);
 156
 157                xioctl(fd, MEMERASE, &erase);
 158
 159                /* format for JFFS2 ? */
 160                if (!(flags & OPTION_J))
 161                        continue;
 162
 163                /* write cleanmarker */
 164                if (flags & IS_NAND) {
 165                        struct mtd_oob_buf oob;
 166
 167                        oob.ptr = (unsigned char *) &cleanmarker;
 168                        oob.start = erase.start + clmpos;
 169                        oob.length = clmlen;
 170                        xioctl(fd, MEMWRITEOOB, &oob);
 171                } else {
 172                        xlseek(fd, erase.start, SEEK_SET);
 173                        /* if (lseek(fd, erase.start, SEEK_SET) < 0) {
 174                                bb_perror_msg("MTD %s failure", "seek");
 175                                continue;
 176                        } */
 177                        xwrite(fd, &cleanmarker, sizeof(cleanmarker));
 178                        /* if (write(fd, &cleanmarker, sizeof(cleanmarker)) != sizeof(cleanmarker)) {
 179                                bb_perror_msg("MTD %s failure", "write");
 180                                continue;
 181                        } */
 182                }
 183                if (!(flags & OPTION_Q))
 184                        printf(" Cleanmarker written at %x.", erase.start);
 185        }
 186        if (!(flags & OPTION_Q)) {
 187                show_progress(&meminfo, &erase);
 188                bb_putchar('\n');
 189        }
 190
 191        if (ENABLE_FEATURE_CLEAN_UP)
 192                close(fd);
 193        return EXIT_SUCCESS;
 194}
 195