aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Genoud <richard.genoud@gmail.com>2014-06-24 12:12:59 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2014-06-25 17:37:01 +0200
commitf17fbe1d365d935b486ece2172043d3eeb8a999b (patch)
tree32ee37903aac28548ff3cea97da046b95b6f0022
parentcbf3bfa57a419202c2bc26f3ff8ae21d3d3bf8b2 (diff)
downloadbusybox-w32-f17fbe1d365d935b486ece2172043d3eeb8a999b.tar.gz
busybox-w32-f17fbe1d365d935b486ece2172043d3eeb8a999b.tar.bz2
busybox-w32-f17fbe1d365d935b486ece2172043d3eeb8a999b.zip
nanddump: add options --bb=skipbad and padbad
In mtd-utils, the bad block options changed in favor of --bb=[skipbad|padbad|dumpbad] and omitbad has been removed. This patch add the --bb=skipbad and padbad methods to busybox' nanddump. padbad is the current default behaviour. The difference between skipbad and omitbad is this one: On a 16K block NAND, if the 1st block of mtd0 is bad, we'll have: nanddump -b -l 16384 /dev/mtd0 | wc -c 0 nanddump --bb=skipbad -l 16384 /dev/mtd0 | wc -c 16384 <- data from 1st good block Signed-off-by: Richard Genoud <richard.genoud@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--miscutils/nandwrite.c65
1 files changed, 56 insertions, 9 deletions
diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c
index 8c4da802f..a64b95bc5 100644
--- a/miscutils/nandwrite.c
+++ b/miscutils/nandwrite.c
@@ -36,7 +36,7 @@
36//usage: "\n -s ADDR Start address" 36//usage: "\n -s ADDR Start address"
37 37
38//usage:#define nanddump_trivial_usage 38//usage:#define nanddump_trivial_usage
39//usage: "[-o] [-b] [-s ADDR] [-l LEN] [-f FILE] MTD_DEVICE" 39//usage: "[-o] [-b|--bb=padbad|skipbad] [-s ADDR] [-l LEN] [-f FILE] MTD_DEVICE"
40//usage:#define nanddump_full_usage "\n\n" 40//usage:#define nanddump_full_usage "\n\n"
41//usage: "Dump MTD_DEVICE\n" 41//usage: "Dump MTD_DEVICE\n"
42//usage: "\n -o Dump oob data" 42//usage: "\n -o Dump oob data"
@@ -44,6 +44,12 @@
44//usage: "\n -s ADDR Start address" 44//usage: "\n -s ADDR Start address"
45//usage: "\n -l LEN Length" 45//usage: "\n -l LEN Length"
46//usage: "\n -f FILE Dump to file ('-' for stdout)" 46//usage: "\n -f FILE Dump to file ('-' for stdout)"
47//usage: "\n --bb=METHOD:"
48//usage: "\n skipbad: skip bad blocks"
49//usage: "\n padbad: substitute bad blocks by 0xff (default)"
50//usage: "\n The difference between omit and skip bad block is that in the omit"
51//usage: "\n case, the length of the bad block is counted as part of the total"
52//usage: "\n dump length, and in the skip case, it's not."
47 53
48#include "libbb.h" 54#include "libbb.h"
49#include <mtd/mtd-user.h> 55#include <mtd/mtd-user.h>
@@ -57,6 +63,11 @@
57#define OPT_b (1 << 2) 63#define OPT_b (1 << 2)
58#define OPT_f (1 << 3) 64#define OPT_f (1 << 3)
59#define OPT_l (1 << 4) 65#define OPT_l (1 << 4)
66#define OPT_bb (1 << 5) /* must be the last one in the list */
67
68#define BB_PADBAD (1 << 0)
69#define BB_SKIPBAD (1 << 1)
70#define BB_OMITBAD (1 << 2)
60 71
61/* helper for writing out 0xff for bad blocks pad */ 72/* helper for writing out 0xff for bad blocks pad */
62static void dump_bad(struct mtd_info_user *meminfo, unsigned len, int oob) 73static void dump_bad(struct mtd_info_user *meminfo, unsigned len, int oob)
@@ -102,6 +113,7 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
102 /* Buffer for OOB data */ 113 /* Buffer for OOB data */
103 unsigned char *oobbuf; 114 unsigned char *oobbuf;
104 unsigned opts; 115 unsigned opts;
116 unsigned bb_method = BB_PADBAD;
105 int fd; 117 int fd;
106 ssize_t cnt; 118 ssize_t cnt;
107 unsigned mtdoffset, meminfo_writesize, blockstart, limit; 119 unsigned mtdoffset, meminfo_writesize, blockstart, limit;
@@ -109,11 +121,14 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
109 struct mtd_info_user meminfo; 121 struct mtd_info_user meminfo;
110 struct mtd_oob_buf oob; 122 struct mtd_oob_buf oob;
111 unsigned char *filebuf; 123 unsigned char *filebuf;
112 const char *opt_s = "0", *opt_f = "-", *opt_l; 124 const char *opt_s = "0", *opt_f = "-", *opt_l, *opt_bb;
125 static const char nanddump_longopts[] ALIGN1 =
126 "bb\0" Required_argument "\xff"; /* no short equivalent */
113 127
114 if (IS_NANDDUMP) { 128 if (IS_NANDDUMP) {
115 opt_complementary = "=1"; 129 opt_complementary = "=1";
116 opts = getopt32(argv, "os:bf:l:", &opt_s, &opt_f, &opt_l); 130 applet_long_options = nanddump_longopts;
131 opts = getopt32(argv, "os:bf:l:", &opt_s, &opt_f, &opt_l, &opt_bb);
117 } else { /* nandwrite */ 132 } else { /* nandwrite */
118 opt_complementary = "-1:?2"; 133 opt_complementary = "-1:?2";
119 opts = getopt32(argv, "ps:", &opt_s); 134 opts = getopt32(argv, "ps:", &opt_s);
@@ -138,6 +153,20 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
138 if (length < meminfo.size - mtdoffset) 153 if (length < meminfo.size - mtdoffset)
139 end_addr = mtdoffset + length; 154 end_addr = mtdoffset + length;
140 } 155 }
156 if (IS_NANDDUMP) {
157 if ((opts & OPT_b) && (opts & OPT_bb))
158 bb_show_usage();
159 if (opts & OPT_b)
160 bb_method = BB_OMITBAD;
161 if (opts & OPT_bb) {
162 if (!strcmp("skipbad", opt_bb))
163 bb_method = BB_SKIPBAD;
164 else if (!strcmp("padbad", opt_bb))
165 bb_method = BB_PADBAD;
166 else
167 bb_show_usage();
168 }
169 }
141 170
142 /* Pull it into a CPU register (hopefully) - smaller code that way */ 171 /* Pull it into a CPU register (hopefully) - smaller code that way */
143 meminfo_writesize = meminfo.writesize; 172 meminfo_writesize = meminfo.writesize;
@@ -162,9 +191,16 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
162 tmp = next_good_eraseblock(fd, &meminfo, blockstart); 191 tmp = next_good_eraseblock(fd, &meminfo, blockstart);
163 if (tmp != blockstart) { 192 if (tmp != blockstart) {
164 /* bad block(s), advance mtdoffset */ 193 /* bad block(s), advance mtdoffset */
165 if (IS_NANDDUMP && !(opts & OPT_b)) { 194 if (IS_NANDDUMP) {
166 int bad_len = MIN(tmp, end_addr) - mtdoffset; 195 if (bb_method == BB_PADBAD) {
167 dump_bad(&meminfo, bad_len, opts & OPT_o); 196 int bad_len = MIN(tmp, end_addr) - mtdoffset;
197 dump_bad(&meminfo, bad_len, opts & OPT_o);
198 }
199 /* with option skipbad, increase the total length */
200 if (bb_method == BB_SKIPBAD) {
201 end_addr += (tmp - blockstart);
202 }
203 /* omitbad: do nothing */
168 } 204 }
169 mtdoffset = tmp; 205 mtdoffset = tmp;
170 } 206 }
@@ -182,9 +218,20 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
182 mtdoffset = next_good_eraseblock(fd, &meminfo, blockstart); 218 mtdoffset = next_good_eraseblock(fd, &meminfo, blockstart);
183 if (IS_NANDWRITE) 219 if (IS_NANDWRITE)
184 printf("Writing at 0x%08x\n", mtdoffset); 220 printf("Writing at 0x%08x\n", mtdoffset);
185 else if (mtdoffset > blockstart && !(opts & OPT_b)) { 221 else if (mtdoffset > blockstart) {
186 int bad_len = MIN(mtdoffset, limit) - blockstart; 222 if (bb_method == BB_PADBAD) {
187 dump_bad(&meminfo, bad_len, opts & OPT_o); 223 /* dump FF padded bad block */
224 int bad_len = MIN(mtdoffset, limit) - blockstart;
225 dump_bad(&meminfo, bad_len, opts & OPT_o);
226 } else if (bb_method == BB_SKIPBAD) {
227 /* for skipbad, increase the length */
228 if ((end_addr + mtdoffset - blockstart) > end_addr)
229 end_addr += (mtdoffset - blockstart);
230 else
231 end_addr = ~0;
232 limit = MIN(meminfo.size, end_addr);
233 }
234 /* omitbad: do nothing */
188 } 235 }
189 if (mtdoffset >= limit) 236 if (mtdoffset >= limit)
190 break; 237 break;