2 * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2.1
6 * as published by the Free Software Foundation
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
16 #include <sys/types.h>
17 #include <sys/ioctl.h>
18 #include <asm/byteorder.h>
19 #include <mtd/mtd-user.h>
30 #include "../fs-state.h"
39 mtd_open(const char *mtd
, int block
)
43 int i
, ret
, flags
= O_RDWR
| O_SYNC
;
45 if ((fp
= fopen("/proc/mtd", "r"))) {
46 while (fgets(dev
, sizeof(dev
), fp
)) {
47 if (sscanf(dev
, "mtd%d:", &i
) && strstr(dev
, mtd
)) {
48 snprintf(dev
, sizeof(dev
), "/dev/mtd%s/%d", (block
? "block" : ""), i
);
49 ret
= open(dev
, flags
);
51 snprintf(dev
, sizeof(dev
), "/dev/mtd%s%d", (block
? "block" : ""), i
);
52 ret
= open(dev
, flags
);
61 return open(mtd
, flags
);
65 mtd_load(const char *mtd
)
67 struct mtd_info_user mtdInfo
;
68 struct erase_info_user mtdLockInfo
;
71 fd
= mtd_open(mtd
, 0);
73 fprintf(stderr
, "Could not open mtd device: %s\n", mtd
);
77 if (ioctl(fd
, MEMGETINFO
, &mtdInfo
)) {
78 fprintf(stderr
, "Could not get MTD device info from %s\n", mtd
);
83 mtdsize
= mtdInfo
.size
;
84 erasesize
= mtdInfo
.erasesize
;
86 mtdLockInfo
.start
= 0;
87 mtdLockInfo
.length
= mtdsize
;
88 ioctl(fd
, MEMUNLOCK
, &mtdLockInfo
);
94 mtd_erase(int fd
, int first_block
, int num_blocks
)
96 struct erase_info_user eiu
;
98 eiu
.length
= erasesize
;
99 for (eiu
.start
= first_block
* erasesize
;
100 eiu
.start
< mtdsize
&& eiu
.start
< (first_block
+ num_blocks
) * erasesize
;
101 eiu
.start
+= erasesize
) {
102 fprintf(stderr
, "erasing %x %x\n", eiu
.start
, erasesize
);
103 ioctl(fd
, MEMUNLOCK
, &eiu
);
104 if (ioctl(fd
, MEMERASE
, &eiu
))
105 fprintf(stderr
, "Failed to erase block at 0x%x\n", eiu
.start
);
112 struct mtd_info_user mtdinfo
;
113 int ret
= ioctl(fd
, MEMGETINFO
, &mtdinfo
);
116 fprintf(stderr
, "ioctl(%d, MEMGETINFO) failed: %s\n", fd
, strerror(errno
));
118 struct erase_info_user mtdlock
;
121 mtdlock
.length
= mtdinfo
.size
;
122 ioctl(fd
, MEMUNLOCK
, &mtdlock
);
129 mtd_read_buffer(int fd
, void *buf
, int offset
, int length
)
131 if (lseek(fd
, offset
, SEEK_SET
) == (off_t
) -1) {
132 fprintf(stderr
, "lseek/read failed\n");
136 if (read(fd
, buf
, length
) == -1) {
137 fprintf(stderr
, "read failed\n");
145 mtd_write_buffer(int fd
, void *buf
, int offset
, int length
)
147 if (lseek(fd
, offset
, SEEK_SET
) == (off_t
) -1) {
148 fprintf(stderr
, "lseek/write failed at offset %d\n", offset
);
153 if (write(fd
, buf
, length
) == -1) {
154 fprintf(stderr
, "write failed\n");
162 mtd_identify(char *mtd
)
164 int fd
= mtd_load(mtd
);
170 fprintf(stderr
, "reading %s failed\n", mtd
);
174 sz
= read(fd
, &deadc0de
, sizeof(deadc0de
));
177 if (sz
!= sizeof(deadc0de
)) {
178 fprintf(stderr
, "reading %s failed: %s\n", mtd
, strerror(errno
));
182 if (deadc0de
== 0x4f575254)
185 deadc0de
= __be32_to_cpu(deadc0de
);
186 jffs2
= __be16_to_cpu(deadc0de
>> 16);
188 if (jffs2
== 0x1985) {
189 fprintf(stderr
, "jffs2 is ready\n");
193 if (deadc0de
== 0xdeadc0de) {
194 fprintf(stderr
, "jffs2 is not ready - marker found\n");
198 fprintf(stderr
, "No jffs2 marker was found\n");