diff options
author | Baruch Siach <baruch@tkos.co.il> | 2010-08-25 16:36:17 +0200 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2010-08-25 16:36:17 +0200 |
commit | 6f32ea4039535c48759a217fd6352193846a393c (patch) | |
tree | dead4ac04b0f2d6c44f7d80172f8b2756b9cfd7c | |
parent | 159677c8842b985c9365b82178b97456ca8a1727 (diff) | |
download | busybox-w32-6f32ea4039535c48759a217fd6352193846a393c.tar.gz busybox-w32-6f32ea4039535c48759a217fd6352193846a393c.tar.bz2 busybox-w32-6f32ea4039535c48759a217fd6352193846a393c.zip |
nandwrite: new applet
function old new delta
nandwrite_main - 382 +382
packed_usage 27119 27135 +16
applet_names 2275 2285 +10
applet_main 1340 1344 +4
applet_nameofs 670 672 +2
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 4/0 up/down: 414/0) Total: 414 bytes
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
-rw-r--r-- | miscutils/nandwrite.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c new file mode 100644 index 000000000..a20f7f384 --- /dev/null +++ b/miscutils/nandwrite.c | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * nandwrite.c - ported to busybox from mtd-utils | ||
3 | * | ||
4 | * Author: Baruch Siach <baruch@tkos.co.il>, Orex Computed Radiography | ||
5 | * | ||
6 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
7 | * | ||
8 | * TODO: add support for large (>4GB) MTD devices | ||
9 | */ | ||
10 | |||
11 | //applet:IF_NANDWRITE(APPLET(nandwrite, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | ||
12 | |||
13 | //kbuild:lib-$(CONFIG_NANDWRITE) += nandwrite.o | ||
14 | |||
15 | //config:config NANDWRITE | ||
16 | //config: bool "nandwrite" | ||
17 | //config: default n | ||
18 | //config: depends on PLATFORM_LINUX | ||
19 | //config: help | ||
20 | //config: Write to the specified MTD device, with bad blocks awareness | ||
21 | |||
22 | #include "libbb.h" | ||
23 | #include <mtd/mtd-user.h> | ||
24 | |||
25 | //usage:#define nandwrite_trivial_usage | ||
26 | //usage: "[-p] [-s ADDR] MTD_DEVICE [FILE]" | ||
27 | //usage:#define nandwrite_full_usage "\n\n" | ||
28 | //usage: "Write to the specified MTD device\n" | ||
29 | //usage: "\nOptions:" | ||
30 | //usage: "\n -p Pad to page size" | ||
31 | //usage: "\n -s ADDR Start address" | ||
32 | |||
33 | static unsigned next_good_eraseblock(int fd, struct mtd_info_user *meminfo, | ||
34 | unsigned block_offset) | ||
35 | { | ||
36 | while (1) { | ||
37 | loff_t offs; | ||
38 | if (block_offset >= meminfo->size) | ||
39 | bb_error_msg_and_die("not enough space in MTD device"); | ||
40 | offs = block_offset; | ||
41 | if (xioctl(fd, MEMGETBADBLOCK, &offs) == 0) | ||
42 | return block_offset; | ||
43 | /* ioctl returned 1 => "bad block" */ | ||
44 | printf("Skipping bad block at 0x%08x\n", block_offset); | ||
45 | block_offset += meminfo->erasesize; | ||
46 | } | ||
47 | } | ||
48 | |||
49 | int nandwrite_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
50 | int nandwrite_main(int argc UNUSED_PARAM, char **argv) | ||
51 | { | ||
52 | unsigned opts; | ||
53 | int fd; | ||
54 | ssize_t cnt; | ||
55 | unsigned mtdoffset, meminfo_writesize; | ||
56 | struct mtd_info_user meminfo; | ||
57 | unsigned char *filebuf; | ||
58 | const char *opt_s = "0"; | ||
59 | enum { | ||
60 | OPT_p = (1 << 0), | ||
61 | OPT_s = (1 << 1), | ||
62 | }; | ||
63 | |||
64 | opt_complementary = "-1:?2"; | ||
65 | opts = getopt32(argv, "ps:", &opt_s); | ||
66 | argv += optind; | ||
67 | |||
68 | if (argv[1]) | ||
69 | xmove_fd(xopen_stdin(argv[1]), STDIN_FILENO); | ||
70 | |||
71 | fd = xopen(argv[0], O_RDWR); | ||
72 | xioctl(fd, MEMGETINFO, &meminfo); | ||
73 | |||
74 | mtdoffset = xatou(opt_s); | ||
75 | |||
76 | /* Pull it into a CPU register (hopefully) - smaller code that way */ | ||
77 | meminfo_writesize = meminfo.writesize; | ||
78 | |||
79 | if (mtdoffset & (meminfo_writesize - 1)) | ||
80 | bb_error_msg_and_die("start address is not page aligned"); | ||
81 | |||
82 | filebuf = xmalloc(meminfo_writesize); | ||
83 | |||
84 | cnt = -1; | ||
85 | while (mtdoffset < meminfo.size) { | ||
86 | unsigned blockstart = mtdoffset & ~(meminfo.erasesize - 1); | ||
87 | if (blockstart == mtdoffset) { | ||
88 | /* starting a new eraseblock */ | ||
89 | mtdoffset = next_good_eraseblock(fd, &meminfo, blockstart); | ||
90 | printf("Writing at 0x%08x\n", mtdoffset); | ||
91 | } | ||
92 | /* get some more data from input */ | ||
93 | cnt = full_read(STDIN_FILENO, filebuf, meminfo_writesize); | ||
94 | if (cnt == 0) { | ||
95 | /* even with -p, we do not pad past the end of input | ||
96 | * (-p only zero-pads last incomplete page) | ||
97 | */ | ||
98 | break; | ||
99 | } | ||
100 | if (cnt < meminfo_writesize) { | ||
101 | if (!(opts & OPT_p)) | ||
102 | bb_error_msg_and_die("input size is not rounded up to page size, " | ||
103 | "use -p to zero pad"); | ||
104 | /* zero pad to end of write block */ | ||
105 | memset(filebuf + cnt, 0, meminfo_writesize - cnt); | ||
106 | } | ||
107 | xlseek(fd, mtdoffset, SEEK_SET); | ||
108 | xwrite(fd, filebuf, meminfo_writesize); | ||
109 | mtdoffset += meminfo_writesize; | ||
110 | if (cnt < meminfo_writesize) | ||
111 | break; | ||
112 | } | ||
113 | |||
114 | if (cnt != 0) { | ||
115 | /* We filled entire MTD, but did we reach EOF on input? */ | ||
116 | if (full_read(STDIN_FILENO, filebuf, meminfo_writesize) != 0) { | ||
117 | /* no */ | ||
118 | bb_error_msg_and_die("not enough space in MTD device"); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | if (ENABLE_FEATURE_CLEAN_UP) { | ||
123 | free(filebuf); | ||
124 | close(fd); | ||
125 | } | ||
126 | |||
127 | return EXIT_SUCCESS; | ||
128 | } | ||