aboutsummaryrefslogtreecommitdiff
path: root/miscutils
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2014-06-30 21:13:06 +0100
committerRon Yorston <rmy@pobox.com>2014-06-30 21:13:06 +0100
commit099e8b6438345baae560a629d548af07a8c3125c (patch)
tree71b5600b22b0019af675e4a991394ce32c8207c5 /miscutils
parente19594cc6e49e78fa50a654f15cf9a04e77d054a (diff)
parent184b2669175e562d58894e22f6320cebf3316c25 (diff)
downloadbusybox-w32-099e8b6438345baae560a629d548af07a8c3125c.tar.gz
busybox-w32-099e8b6438345baae560a629d548af07a8c3125c.tar.bz2
busybox-w32-099e8b6438345baae560a629d548af07a8c3125c.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'miscutils')
-rw-r--r--miscutils/nandwrite.c63
1 files changed, 48 insertions, 15 deletions
diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c
index e3f9b565d..29ff351a3 100644
--- a/miscutils/nandwrite.c
+++ b/miscutils/nandwrite.c
@@ -36,14 +36,16 @@
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] [--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"
43//usage: "\n -b Omit bad block from the dump"
44//usage: "\n -s ADDR Start address" 43//usage: "\n -s ADDR Start address"
45//usage: "\n -l LEN Length" 44//usage: "\n -l LEN Length"
46//usage: "\n -f FILE Dump to file ('-' for stdout)" 45//usage: "\n -f FILE Dump to file ('-' for stdout)"
46//usage: "\n --bb=METHOD:"
47//usage: "\n skipbad: skip bad blocks"
48//usage: "\n padbad: substitute bad blocks by 0xff (default)"
47 49
48#include "libbb.h" 50#include "libbb.h"
49#include <mtd/mtd-user.h> 51#include <mtd/mtd-user.h>
@@ -54,9 +56,12 @@
54#define OPT_p (1 << 0) /* nandwrite only */ 56#define OPT_p (1 << 0) /* nandwrite only */
55#define OPT_o (1 << 0) /* nanddump only */ 57#define OPT_o (1 << 0) /* nanddump only */
56#define OPT_s (1 << 1) 58#define OPT_s (1 << 1)
57#define OPT_b (1 << 2) 59#define OPT_f (1 << 2)
58#define OPT_f (1 << 3) 60#define OPT_l (1 << 3)
59#define OPT_l (1 << 4) 61#define OPT_bb (1 << 4) /* must be the last one in the list */
62
63#define BB_PADBAD (1 << 0)
64#define BB_SKIPBAD (1 << 1)
60 65
61/* helper for writing out 0xff for bad blocks pad */ 66/* helper for writing out 0xff for bad blocks pad */
62static void dump_bad(struct mtd_info_user *meminfo, unsigned len, int oob) 67static void dump_bad(struct mtd_info_user *meminfo, unsigned len, int oob)
@@ -64,8 +69,8 @@ static void dump_bad(struct mtd_info_user *meminfo, unsigned len, int oob)
64 unsigned char buf[meminfo->writesize]; 69 unsigned char buf[meminfo->writesize];
65 unsigned count; 70 unsigned count;
66 71
67 /* round len to the next page */ 72 /* round len to the next page only if len is not already on a page */
68 len = (len | ~(meminfo->writesize - 1)) + 1; 73 len = ((len - 1) | (meminfo->writesize - 1)) + 1;
69 74
70 memset(buf, 0xff, sizeof(buf)); 75 memset(buf, 0xff, sizeof(buf));
71 for (count = 0; count < len; count += meminfo->writesize) { 76 for (count = 0; count < len; count += meminfo->writesize) {
@@ -102,6 +107,7 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
102 /* Buffer for OOB data */ 107 /* Buffer for OOB data */
103 unsigned char *oobbuf; 108 unsigned char *oobbuf;
104 unsigned opts; 109 unsigned opts;
110 unsigned bb_method = BB_SKIPBAD;
105 int fd; 111 int fd;
106 ssize_t cnt; 112 ssize_t cnt;
107 unsigned mtdoffset, meminfo_writesize, blockstart, limit; 113 unsigned mtdoffset, meminfo_writesize, blockstart, limit;
@@ -109,11 +115,14 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
109 struct mtd_info_user meminfo; 115 struct mtd_info_user meminfo;
110 struct mtd_oob_buf oob; 116 struct mtd_oob_buf oob;
111 unsigned char *filebuf; 117 unsigned char *filebuf;
112 const char *opt_s = "0", *opt_f = "-", *opt_l; 118 const char *opt_s = "0", *opt_f = "-", *opt_l, *opt_bb;
119 static const char nanddump_longopts[] ALIGN1 =
120 "bb\0" Required_argument "\xff"; /* no short equivalent */
113 121
114 if (IS_NANDDUMP) { 122 if (IS_NANDDUMP) {
115 opt_complementary = "=1"; 123 opt_complementary = "=1";
116 opts = getopt32(argv, "os:bf:l:", &opt_s, &opt_f, &opt_l); 124 applet_long_options = nanddump_longopts;
125 opts = getopt32(argv, "os:f:l:", &opt_s, &opt_f, &opt_l, &opt_bb);
117 } else { /* nandwrite */ 126 } else { /* nandwrite */
118 opt_complementary = "-1:?2"; 127 opt_complementary = "-1:?2";
119 opts = getopt32(argv, "ps:", &opt_s); 128 opts = getopt32(argv, "ps:", &opt_s);
@@ -138,6 +147,14 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
138 if (length < meminfo.size - mtdoffset) 147 if (length < meminfo.size - mtdoffset)
139 end_addr = mtdoffset + length; 148 end_addr = mtdoffset + length;
140 } 149 }
150 if (IS_NANDDUMP && (opts & OPT_bb)) {
151 if (strcmp("skipbad", opt_bb) == 0)
152 bb_method = BB_SKIPBAD;
153 else if (strcmp("padbad", opt_bb) == 0)
154 bb_method = BB_PADBAD;
155 else
156 bb_show_usage();
157 }
141 158
142 /* Pull it into a CPU register (hopefully) - smaller code that way */ 159 /* Pull it into a CPU register (hopefully) - smaller code that way */
143 meminfo_writesize = meminfo.writesize; 160 meminfo_writesize = meminfo.writesize;
@@ -162,9 +179,15 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
162 tmp = next_good_eraseblock(fd, &meminfo, blockstart); 179 tmp = next_good_eraseblock(fd, &meminfo, blockstart);
163 if (tmp != blockstart) { 180 if (tmp != blockstart) {
164 /* bad block(s), advance mtdoffset */ 181 /* bad block(s), advance mtdoffset */
165 if (IS_NANDDUMP && !(opts & OPT_b)) { 182 if (IS_NANDDUMP) {
166 int bad_len = MIN(tmp, end_addr) - mtdoffset; 183 if (bb_method == BB_PADBAD) {
167 dump_bad(&meminfo, bad_len, opts & OPT_o); 184 int bad_len = MIN(tmp, end_addr) - mtdoffset;
185 dump_bad(&meminfo, bad_len, opts & OPT_o);
186 }
187 /* with option skipbad, increase the total length */
188 if (bb_method == BB_SKIPBAD) {
189 end_addr += (tmp - blockstart);
190 }
168 } 191 }
169 mtdoffset = tmp; 192 mtdoffset = tmp;
170 } 193 }
@@ -182,9 +205,19 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
182 mtdoffset = next_good_eraseblock(fd, &meminfo, blockstart); 205 mtdoffset = next_good_eraseblock(fd, &meminfo, blockstart);
183 if (IS_NANDWRITE) 206 if (IS_NANDWRITE)
184 printf("Writing at 0x%08x\n", mtdoffset); 207 printf("Writing at 0x%08x\n", mtdoffset);
185 else if (mtdoffset > blockstart && !(opts & OPT_b)) { 208 else if (mtdoffset > blockstart) {
186 int bad_len = MIN(mtdoffset, limit) - blockstart; 209 if (bb_method == BB_PADBAD) {
187 dump_bad(&meminfo, bad_len, opts & OPT_o); 210 /* dump FF padded bad block */
211 int bad_len = MIN(mtdoffset, limit) - blockstart;
212 dump_bad(&meminfo, bad_len, opts & OPT_o);
213 } else if (bb_method == BB_SKIPBAD) {
214 /* for skipbad, increase the length */
215 if ((end_addr + mtdoffset - blockstart) > end_addr)
216 end_addr += (mtdoffset - blockstart);
217 else
218 end_addr = ~0;
219 limit = MIN(meminfo.size, end_addr);
220 }
188 } 221 }
189 if (mtdoffset >= limit) 222 if (mtdoffset >= limit)
190 break; 223 break;