source: MondoRescue/branches/3.3/mindi-busybox/miscutils/flash_eraseall.c@ 3647

Last change on this file since 3647 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 5.3 KB
Line 
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 source tree.
11 */
12
13//usage:#define flash_eraseall_trivial_usage
14//usage: "[-jNq] MTD_DEVICE"
15//usage:#define flash_eraseall_full_usage "\n\n"
16//usage: "Erase an MTD device\n"
17//usage: "\n -j Format the device for jffs2"
18//usage: "\n -N Don't skip bad blocks"
19//usage: "\n -q Don't display progress messages"
20
21#include "libbb.h"
22#include <mtd/mtd-user.h>
23#include <linux/jffs2.h>
24
25#define OPTION_J (1 << 0)
26#define OPTION_N (1 << 1)
27#define OPTION_Q (1 << 2)
28#define IS_NAND (1 << 3)
29
30/* mtd/jffs2-user.h used to have this atrocity:
31extern int target_endian;
32
33#define t16(x) ({ __u16 __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_16(__b); })
34#define t32(x) ({ __u32 __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_32(__b); })
35
36#define cpu_to_je16(x) ((jint16_t){t16(x)})
37#define cpu_to_je32(x) ((jint32_t){t32(x)})
38#define cpu_to_jemode(x) ((jmode_t){t32(x)})
39
40#define je16_to_cpu(x) (t16((x).v16))
41#define je32_to_cpu(x) (t32((x).v32))
42#define jemode_to_cpu(x) (t32((x).m))
43
44but mtd/jffs2-user.h is gone now (at least 2.6.31.6 does not have it anymore)
45*/
46
47/* We always use native endianness */
48#undef cpu_to_je16
49#undef cpu_to_je32
50#define cpu_to_je16(v) ((jint16_t){(v)})
51#define cpu_to_je32(v) ((jint32_t){(v)})
52
53static void show_progress(mtd_info_t *meminfo, erase_info_t *erase)
54{
55 printf("\rErasing %u Kibyte @ %x - %2u%% complete.",
56 (unsigned)meminfo->erasesize / 1024,
57 erase->start,
58 (unsigned) ((unsigned long long) erase->start * 100 / meminfo->size)
59 );
60 fflush_all();
61}
62
63int flash_eraseall_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
64int flash_eraseall_main(int argc UNUSED_PARAM, char **argv)
65{
66 struct jffs2_unknown_node cleanmarker;
67 mtd_info_t meminfo;
68 int fd, clmpos, clmlen;
69 erase_info_t erase;
70 struct stat st;
71 unsigned int flags;
72 char *mtd_name;
73
74 opt_complementary = "=1";
75 flags = getopt32(argv, "jNq");
76
77 mtd_name = argv[optind];
78 fd = xopen(mtd_name, O_RDWR);
79 fstat(fd, &st);
80 if (!S_ISCHR(st.st_mode))
81 bb_error_msg_and_die("%s: not a char device", mtd_name);
82
83 xioctl(fd, MEMGETINFO, &meminfo);
84 erase.length = meminfo.erasesize;
85 if (meminfo.type == MTD_NANDFLASH)
86 flags |= IS_NAND;
87
88 clmpos = 0;
89 clmlen = 8;
90 if (flags & OPTION_J) {
91 uint32_t *crc32_table;
92
93 crc32_table = crc32_filltable(NULL, 0);
94
95 cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
96 cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
97 if (!(flags & IS_NAND))
98 cleanmarker.totlen = cpu_to_je32(sizeof(struct jffs2_unknown_node));
99 else {
100 struct nand_oobinfo oobinfo;
101
102 xioctl(fd, MEMGETOOBSEL, &oobinfo);
103
104 /* Check for autoplacement */
105 if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
106 /* Get the position of the free bytes */
107 clmpos = oobinfo.oobfree[0][0];
108 clmlen = oobinfo.oobfree[0][1];
109 if (clmlen > 8)
110 clmlen = 8;
111 if (clmlen == 0)
112 bb_error_msg_and_die("autoplacement selected and no empty space in oob");
113 } else {
114 /* Legacy mode */
115 switch (meminfo.oobsize) {
116 case 8:
117 clmpos = 6;
118 clmlen = 2;
119 break;
120 case 16:
121 clmpos = 8;
122 /*clmlen = 8;*/
123 break;
124 case 64:
125 clmpos = 16;
126 /*clmlen = 8;*/
127 break;
128 }
129 }
130 cleanmarker.totlen = cpu_to_je32(8);
131 }
132
133 cleanmarker.hdr_crc = cpu_to_je32(
134 crc32_block_endian0(0, &cleanmarker, sizeof(struct jffs2_unknown_node) - 4, crc32_table)
135 );
136 }
137
138 /* Don't want to destroy progress indicator by bb_error_msg's */
139 applet_name = xasprintf("\n%s: %s", applet_name, mtd_name);
140
141 for (erase.start = 0; erase.start < meminfo.size;
142 erase.start += meminfo.erasesize) {
143 if (!(flags & OPTION_N)) {
144 int ret;
145 loff_t offset = erase.start;
146
147 ret = ioctl(fd, MEMGETBADBLOCK, &offset);
148 if (ret > 0) {
149 if (!(flags & OPTION_Q))
150 printf("\nSkipping bad block at 0x%08x\n", erase.start);
151 continue;
152 }
153 if (ret < 0) {
154 /* Black block table is not available on certain flash
155 * types e.g. NOR
156 */
157 if (errno == EOPNOTSUPP) {
158 flags |= OPTION_N;
159 if (flags & IS_NAND)
160 bb_error_msg_and_die("bad block check not available");
161 } else {
162 bb_perror_msg_and_die("MEMGETBADBLOCK error");
163 }
164 }
165 }
166
167 if (!(flags & OPTION_Q))
168 show_progress(&meminfo, &erase);
169
170 xioctl(fd, MEMERASE, &erase);
171
172 /* format for JFFS2 ? */
173 if (!(flags & OPTION_J))
174 continue;
175
176 /* write cleanmarker */
177 if (flags & IS_NAND) {
178 struct mtd_oob_buf oob;
179
180 oob.ptr = (unsigned char *) &cleanmarker;
181 oob.start = erase.start + clmpos;
182 oob.length = clmlen;
183 xioctl(fd, MEMWRITEOOB, &oob);
184 } else {
185 xlseek(fd, erase.start, SEEK_SET);
186 /* if (lseek(fd, erase.start, SEEK_SET) < 0) {
187 bb_perror_msg("MTD %s failure", "seek");
188 continue;
189 } */
190 xwrite(fd, &cleanmarker, sizeof(cleanmarker));
191 /* if (write(fd, &cleanmarker, sizeof(cleanmarker)) != sizeof(cleanmarker)) {
192 bb_perror_msg("MTD %s failure", "write");
193 continue;
194 } */
195 }
196 if (!(flags & OPTION_Q))
197 printf(" Cleanmarker written at %x.", erase.start);
198 }
199 if (!(flags & OPTION_Q)) {
200 show_progress(&meminfo, &erase);
201 bb_putchar('\n');
202 }
203
204 if (ENABLE_FEATURE_CLEAN_UP)
205 close(fd);
206 return EXIT_SUCCESS;
207}
Note: See TracBrowser for help on using the repository browser.