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");