diff options
author | Stefan Seyfried <stefan.seyfried@googlemail.com> | 2009-11-21 18:32:19 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-11-21 18:32:19 +0100 |
commit | d095fd4d95fd6241847f01e4fd674bc177310c33 (patch) | |
tree | a860321d92a028c5e54f227497d9605fe1dc5a10 | |
parent | 102ff76c845746f9c0bae65299176a0a49f85260 (diff) | |
download | busybox-w32-d095fd4d95fd6241847f01e4fd674bc177310c33.tar.gz busybox-w32-d095fd4d95fd6241847f01e4fd674bc177310c33.tar.bz2 busybox-w32-d095fd4d95fd6241847f01e4fd674bc177310c33.zip |
flashcp: new applet by Stefan Seyfried. +900 bytes
Signed-off-by: Stefan Seyfried <stefan.seyfried@googlemail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | include/applets.h | 1 | ||||
-rw-r--r-- | include/usage.h | 11 | ||||
-rw-r--r-- | miscutils/Config.in | 7 | ||||
-rw-r--r-- | miscutils/Kbuild | 1 | ||||
-rw-r--r-- | miscutils/flashcp.c | 151 |
5 files changed, 169 insertions, 2 deletions
diff --git a/include/applets.h b/include/applets.h index 60fb8bf2b..15ccf9cea 100644 --- a/include/applets.h +++ b/include/applets.h | |||
@@ -160,6 +160,7 @@ IF_FINDFS(APPLET(findfs, _BB_DIR_SBIN, _BB_SUID_MAYBE)) | |||
160 | IF_FLASH_ERASEALL(APPLET(flash_eraseall, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 160 | IF_FLASH_ERASEALL(APPLET(flash_eraseall, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
161 | IF_FLASH_LOCK(APPLET_ODDNAME(flash_lock, flash_lock_unlock, _BB_DIR_USR_SBIN, _BB_SUID_DROP, flash_lock)) | 161 | IF_FLASH_LOCK(APPLET_ODDNAME(flash_lock, flash_lock_unlock, _BB_DIR_USR_SBIN, _BB_SUID_DROP, flash_lock)) |
162 | IF_FLASH_UNLOCK(APPLET_ODDNAME(flash_unlock, flash_lock_unlock, _BB_DIR_USR_SBIN, _BB_SUID_DROP, flash_unlock)) | 162 | IF_FLASH_UNLOCK(APPLET_ODDNAME(flash_unlock, flash_lock_unlock, _BB_DIR_USR_SBIN, _BB_SUID_DROP, flash_unlock)) |
163 | IF_FLASHCP(APPLET(flashcp, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | ||
163 | IF_FOLD(APPLET(fold, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 164 | IF_FOLD(APPLET(fold, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
164 | IF_FREE(APPLET(free, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 165 | IF_FREE(APPLET(free, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
165 | IF_FREERAMDISK(APPLET(freeramdisk, _BB_DIR_SBIN, _BB_SUID_DROP)) | 166 | IF_FREERAMDISK(APPLET(freeramdisk, _BB_DIR_SBIN, _BB_SUID_DROP)) |
diff --git a/include/usage.h b/include/usage.h index 0d01577c7..eae9650ca 100644 --- a/include/usage.h +++ b/include/usage.h | |||
@@ -1286,8 +1286,15 @@ | |||
1286 | #define flash_eraseall_full_usage "\n\n" \ | 1286 | #define flash_eraseall_full_usage "\n\n" \ |
1287 | "Erase an MTD device\n" \ | 1287 | "Erase an MTD device\n" \ |
1288 | "\nOptions:" \ | 1288 | "\nOptions:" \ |
1289 | "\n -j format the device for jffs2" \ | 1289 | "\n -j Format the device for jffs2" \ |
1290 | "\n -q don't display progress messages" | 1290 | "\n -q Don't display progress messages" \ |
1291 | |||
1292 | #define flashcp_trivial_usage \ | ||
1293 | "-v FILE MTD_DEVICE" | ||
1294 | #define flashcp_full_usage "\n\n" \ | ||
1295 | "Copy an image to MTD device\n" \ | ||
1296 | "\nOptions:" \ | ||
1297 | "\n -v Verbose" \ | ||
1291 | 1298 | ||
1292 | #define fold_trivial_usage \ | 1299 | #define fold_trivial_usage \ |
1293 | "[-bs] [-w WIDTH] [FILE]" | 1300 | "[-bs] [-w WIDTH] [FILE]" |
diff --git a/miscutils/Config.in b/miscutils/Config.in index 842f7f9d2..ebf98f98c 100644 --- a/miscutils/Config.in +++ b/miscutils/Config.in | |||
@@ -272,6 +272,13 @@ config FBSPLASH | |||
272 | "NN" (ASCII decimal number) - percentage to show on progress bar | 272 | "NN" (ASCII decimal number) - percentage to show on progress bar |
273 | "exit" - well you guessed it | 273 | "exit" - well you guessed it |
274 | 274 | ||
275 | config FLASHCP | ||
276 | bool "flashcp" | ||
277 | default n | ||
278 | help | ||
279 | The flashcp binary, inspired by mtd-utils as of git head 5eceb74f7. | ||
280 | This utility is used to copy images into a MTD device. | ||
281 | |||
275 | config FLASH_LOCK | 282 | config FLASH_LOCK |
276 | bool "flash_lock" | 283 | bool "flash_lock" |
277 | default n | 284 | default n |
diff --git a/miscutils/Kbuild b/miscutils/Kbuild index 22a9adb34..bbfa93dc7 100644 --- a/miscutils/Kbuild +++ b/miscutils/Kbuild | |||
@@ -17,6 +17,7 @@ lib-$(CONFIG_DEVFSD) += devfsd.o | |||
17 | lib-$(CONFIG_DEVMEM) += devmem.o | 17 | lib-$(CONFIG_DEVMEM) += devmem.o |
18 | lib-$(CONFIG_EJECT) += eject.o | 18 | lib-$(CONFIG_EJECT) += eject.o |
19 | lib-$(CONFIG_FBSPLASH) += fbsplash.o | 19 | lib-$(CONFIG_FBSPLASH) += fbsplash.o |
20 | lib-$(CONFIG_FLASHCP) += flashcp.o | ||
20 | lib-$(CONFIG_FLASH_ERASEALL) += flash_eraseall.o | 21 | lib-$(CONFIG_FLASH_ERASEALL) += flash_eraseall.o |
21 | lib-$(CONFIG_FLASH_LOCK) += flash_lock_unlock.o | 22 | lib-$(CONFIG_FLASH_LOCK) += flash_lock_unlock.o |
22 | lib-$(CONFIG_FLASH_UNLOCK) += flash_lock_unlock.o | 23 | lib-$(CONFIG_FLASH_UNLOCK) += flash_lock_unlock.o |
diff --git a/miscutils/flashcp.c b/miscutils/flashcp.c new file mode 100644 index 000000000..9472c7527 --- /dev/null +++ b/miscutils/flashcp.c | |||
@@ -0,0 +1,151 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * busybox reimplementation of flashcp | ||
4 | * | ||
5 | * (C) 2009 Stefan Seyfried <seife@sphairon.com> | ||
6 | * | ||
7 | * Licensed under GPLv2, see file LICENSE in this tarball for details. | ||
8 | */ | ||
9 | |||
10 | #include "libbb.h" | ||
11 | #include <mtd/mtd-user.h> | ||
12 | |||
13 | #define MTD_DEBUG 0 | ||
14 | |||
15 | #define OPT_v (1 << 0) | ||
16 | |||
17 | #define BUFSIZE (8 * 1024) | ||
18 | |||
19 | static void progress(int mode, uoff_t count, uoff_t total) | ||
20 | { | ||
21 | uoff_t percent; | ||
22 | |||
23 | if (!option_mask32) //if (!(option_mask32 & OPT_v)) | ||
24 | return; | ||
25 | percent = count * 100; | ||
26 | if (total) | ||
27 | percent = (unsigned) (percent / total); | ||
28 | printf("\r%s: %"OFF_FMT"u/%"OFF_FMT"u (%u%%) ", | ||
29 | (mode == 0) ? "Erasing block" : ((mode == 1) ? "Writing kb" : "Verifying kb"), | ||
30 | count, total, (unsigned)percent); | ||
31 | fflush_all(); | ||
32 | } | ||
33 | |||
34 | static void progress_newline(void) | ||
35 | { | ||
36 | if (!option_mask32) //if (!(option_mask32 & OPT_v)) | ||
37 | return; | ||
38 | bb_putchar('\n'); | ||
39 | } | ||
40 | |||
41 | int flashcp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
42 | int flashcp_main(int argc UNUSED_PARAM, char **argv) | ||
43 | { | ||
44 | int fd_f, fd_d; /* input file and mtd device file descriptors */ | ||
45 | int i; | ||
46 | uoff_t erase_count; | ||
47 | unsigned opts; | ||
48 | struct mtd_info_user mtd; | ||
49 | struct erase_info_user e; | ||
50 | struct stat statb; | ||
51 | // const char *filename, *devicename; | ||
52 | RESERVE_CONFIG_UBUFFER(buf, BUFSIZE); | ||
53 | RESERVE_CONFIG_UBUFFER(buf2, BUFSIZE); | ||
54 | |||
55 | opt_complementary = "=2"; /* exactly 2 non-option args: file, dev */ | ||
56 | opts = getopt32(argv, "v"); | ||
57 | argv += optind; | ||
58 | // filename = *argv++; | ||
59 | // devicename = *argv; | ||
60 | #define filename argv[0] | ||
61 | #define devicename argv[1] | ||
62 | |||
63 | /* open input file and mtd device and do sanity checks */ | ||
64 | fd_f = xopen(filename, O_RDONLY); | ||
65 | fstat(fd_f, &statb); | ||
66 | fd_d = xopen(devicename, O_SYNC | O_RDWR); | ||
67 | #if !MTD_DEBUG | ||
68 | if (ioctl(fd_d, MEMGETINFO, &mtd) < 0) { | ||
69 | bb_error_msg_and_die("%s is not a MTD flash device", devicename); | ||
70 | } | ||
71 | if (statb.st_size > mtd.size) { | ||
72 | bb_error_msg_and_die("%s bigger than %s", filename, devicename); | ||
73 | } | ||
74 | #else | ||
75 | mtd.erasesize = 64 * 1024; | ||
76 | #endif | ||
77 | |||
78 | /* always erase a complete block */ | ||
79 | erase_count = (uoff_t)(statb.st_size + mtd.erasesize - 1) / mtd.erasesize; | ||
80 | /* erase 1 block at a time to be able to give verbose output */ | ||
81 | e.length = mtd.erasesize; | ||
82 | #if 0 | ||
83 | /* (1) bloat | ||
84 | * (2) will it work for multi-gigabyte devices? | ||
85 | * (3) worse wrt error detection granularity | ||
86 | */ | ||
87 | /* optimization: if not verbose, erase in one go */ | ||
88 | if (!opts) { // if (!(opts & OPT_v)) | ||
89 | e.length = mtd.erasesize * erase_count; | ||
90 | erase_count = 1; | ||
91 | } | ||
92 | #endif | ||
93 | e.start = 0; | ||
94 | for (i = 1; i <= erase_count; i++) { | ||
95 | progress(0, i, erase_count); | ||
96 | errno = 0; | ||
97 | #if !MTD_DEBUG | ||
98 | if (ioctl(fd_d, MEMERASE, &e) < 0) { | ||
99 | bb_perror_msg_and_die("erase error at 0x%llx on %s", | ||
100 | (long long)e.start, devicename); | ||
101 | } | ||
102 | #else | ||
103 | usleep(100*1000); | ||
104 | #endif | ||
105 | e.start += mtd.erasesize; | ||
106 | } | ||
107 | progress_newline(); | ||
108 | |||
109 | /* doing this outer loop gives significantly smaller code | ||
110 | * than doing two separate loops for writing and verifying */ | ||
111 | for (i = 1; i <= 2; i++) { | ||
112 | uoff_t done; | ||
113 | unsigned count; | ||
114 | |||
115 | xlseek(fd_f, 0, SEEK_SET); | ||
116 | xlseek(fd_d, 0, SEEK_SET); | ||
117 | done = 0; | ||
118 | count = BUFSIZE; | ||
119 | while (1) { | ||
120 | uoff_t rem = statb.st_size - done; | ||
121 | if (rem == 0) | ||
122 | break; | ||
123 | if (rem < BUFSIZE) | ||
124 | count = rem; | ||
125 | progress(i, done / 1024, (uoff_t)statb.st_size / 1024); | ||
126 | xread(fd_f, buf, count); | ||
127 | if (i == 1) { | ||
128 | int ret; | ||
129 | errno = 0; | ||
130 | ret = full_write(fd_d, buf, count); | ||
131 | if (ret != count) { | ||
132 | bb_perror_msg_and_die("write error at 0x%"OFF_FMT"x on %s, " | ||
133 | "write returned %d", | ||
134 | done, devicename, ret); | ||
135 | } | ||
136 | } else { /* i == 2 */ | ||
137 | xread(fd_d, buf2, count); | ||
138 | if (memcmp(buf, buf2, count)) { | ||
139 | bb_error_msg_and_die("verification mismatch at 0x%"OFF_FMT"x", done); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | done += count; | ||
144 | } | ||
145 | |||
146 | progress_newline(); | ||
147 | } | ||
148 | /* we won't come here if there was an error */ | ||
149 | |||
150 | return EXIT_SUCCESS; | ||
151 | } | ||