Exemple #1
0
static int concat_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
	struct mtd_concat *concat = CONCAT(mtd);
	int i, err = 0;

	for (i = 0; i < concat->num_subdev; i++) {
		struct mtd_info *subdev = concat->subdev[i];
		uint64_t size;

		if (ofs >= subdev->size) {
			size = 0;
			ofs -= subdev->size;
			continue;
		}
		if (ofs + len > subdev->size)
			size = subdev->size - ofs;
		else
			size = len;

		err = mtd_unlock(subdev, ofs, size);
		if (err)
			break;

		len -= size;
		if (len == 0)
			break;

		err = -EINVAL;
		ofs = 0;
	}

	return err;
}
Exemple #2
0
static ssize_t mtd_op_protect(struct cdev *cdev, size_t count, loff_t offset, int prot)
{
	struct mtd_info *mtd = cdev->priv;

	if (!mtd->unlock || !mtd->lock)
		return -ENOSYS;

	if (prot)
		return mtd_lock(mtd, offset, count);
	else
		return mtd_unlock(mtd, offset, count);
}
Exemple #3
0
void format_mount_2nd_jffs2(void)
{
        int format = 0;
        char s[256];
        int size;
        int part;
        const char *p;

        if (!wait_action_idle(10)) return;

        if (!mtd_getinfo(SECOND_JFFS2_PARTITION, &part, &size)) return;
	_dprintf("Format 2nd jffs2: %d, %d\n", part, size);

	if(!check_in_rootfs(SECOND_JFFS2_PATH, "2nd_jffs", format))
		return;

        if (!mtd_unlock(SECOND_JFFS2_PARTITION)) {
                error("unlocking");
                return;
        }

        modprobe(JFFS_NAME);
        sprintf(s, MTD_BLKDEV(%d), part);
        if (mount(s, SECOND_JFFS2_PATH, JFFS_NAME, MS_NOATIME, "") != 0) {
		if( (get_model()==MODEL_RTAC56U || get_model()==MODEL_RTAC56S || get_model()==MODEL_RTAC3200 || get_model()==MODEL_RTAC68U || get_model()==MODEL_RPAC68U || get_model()==MODEL_DSLAC68U || get_model()==MODEL_RTAC87U || get_model()==MODEL_RTAC88U || get_model()==MODEL_RTAC3100 || get_model()==MODEL_RTAC5300 || get_model==MODEL_RTAC5300R || get_model()==MODEL_RTN18U || get_model()==MODEL_RTAC1200G || get_model()==MODEL_RTAC1200GP) ^ (mtd_erase(SECOND_JFFS2_PARTITION)) ){
                        error("formatting");
                        return;
                }

                format = 1;
                if (mount(s, SECOND_JFFS2_PATH, JFFS_NAME, MS_NOATIME, "") != 0) {
                        _dprintf("*** jffs2 2-nd mount error\n");
                        //modprobe_r(JFFS_NAME);
                        error("mounting");
                        return;
                }
        }

	sprintf(s, "rm -rf %s/*", SECOND_JFFS2_PATH);
        system(s);

        notice_set("2nd_jffs", format ? "Formatted" : "Loaded");

        if (((p = nvram_get("jffs2_exec")) != NULL) && (*p != 0)) {
                chdir(SECOND_JFFS2_PATH);
                system(p);
                chdir("/");
        }
        run_userfile(SECOND_JFFS2_PATH, ".asusrouter", SECOND_JFFS2_PATH, 3);

}
Exemple #4
0
static void test_mtd_unlock(void **state)
{
	int eb = 0xBA;
	struct mtd_dev_info mtd;
	memset(&mtd, 0, sizeof(mtd));
	mtd.bb_allowed = 1;
	mtd.eb_cnt = 1024;
	mtd.eb_size = 128;
	struct erase_info_user ei;
	memset(&ei, 0, sizeof(ei));
	ei.start = eb * mtd.eb_size;
	ei.length = mtd.eb_size;
	expect_ioctl(MEMUNLOCK, 0, &ei);
	int r = mtd_unlock(&mtd, 4, eb);
	assert_int_equal(r, 0);

	(void) state;
}
Exemple #5
0
int main (int argc, char **argv)
{
	int ch, i, boot, imagefd = 0, force, unlocked;
	char *erase[MAX_ARGS], *device = NULL;
	char *fis_layout = NULL;
	size_t offset = 0, part_offset = 0, dump_len = 0;
	enum {
		CMD_ERASE,
		CMD_WRITE,
		CMD_UNLOCK,
		CMD_JFFS2WRITE,
		CMD_FIXTRX,
		CMD_FIXSEAMA,
		CMD_VERIFY,
		CMD_DUMP,
	} cmd = -1;

	erase[0] = NULL;
	boot = 0;
	force = 0;
	buflen = 0;
	quiet = 0;
	no_erase = 0;

	while ((ch = getopt(argc, argv,
#ifdef FIS_SUPPORT
			"F:"
#endif
			"frnqe:d:s:j:p:o:l:")) != -1)
		switch (ch) {
			case 'f':
				force = 1;
				break;
			case 'r':
				boot = 1;
				break;
			case 'n':
				no_erase = 1;
				break;
			case 'j':
				jffs2file = optarg;
				break;
			case 's':
				errno = 0;
				jffs2_skip_bytes = strtoul(optarg, 0, 0);
				if (errno) {
						fprintf(stderr, "-s: illegal numeric string\n");
						usage();
				}
				break;
			case 'q':
				quiet++;
				break;
			case 'e':
				i = 0;
				while ((erase[i] != NULL) && ((i + 1) < MAX_ARGS))
					i++;

				erase[i++] = optarg;
				erase[i] = NULL;
				break;
			case 'd':
				jffs2dir = optarg;
				break;
			case 'p':
				errno = 0;
				part_offset = strtoul(optarg, 0, 0);
				if (errno) {
					fprintf(stderr, "-p: illegal numeric string\n");
					usage();
				}
				break;
			case 'l':
				errno = 0;
				dump_len = strtoul(optarg, 0, 0);
				if (errno) {
					fprintf(stderr, "-l: illegal numeric string\n");
					usage();
				}
				break;
			case 'o':
				errno = 0;
				offset = strtoul(optarg, 0, 0);
				if (errno) {
					fprintf(stderr, "-o: illegal numeric string\n");
					usage();
				}
				break;
#ifdef FIS_SUPPORT
			case 'F':
				fis_layout = optarg;
				break;
#endif
			case '?':
			default:
				usage();
		}
	argc -= optind;
	argv += optind;

	if (argc < 2)
		usage();

	if ((strcmp(argv[0], "unlock") == 0) && (argc == 2)) {
		cmd = CMD_UNLOCK;
		device = argv[1];
	} else if ((strcmp(argv[0], "erase") == 0) && (argc == 2)) {
		cmd = CMD_ERASE;
		device = argv[1];
	} else if (((strcmp(argv[0], "fixtrx") == 0) && (argc == 2)) && mtd_fixtrx) {
		cmd = CMD_FIXTRX;
		device = argv[1];
	} else if (((strcmp(argv[0], "fixseama") == 0) && (argc == 2)) && mtd_fixseama) {
		cmd = CMD_FIXSEAMA;
		device = argv[1];
	} else if ((strcmp(argv[0], "verify") == 0) && (argc == 3)) {
		cmd = CMD_VERIFY;
		imagefile = argv[1];
		device = argv[2];
	} else if ((strcmp(argv[0], "dump") == 0) && (argc == 2)) {
		cmd = CMD_DUMP;
		device = argv[1];
	} else if ((strcmp(argv[0], "write") == 0) && (argc == 3)) {
		cmd = CMD_WRITE;
		device = argv[2];

		if (strcmp(argv[1], "-") == 0) {
			imagefile = "<stdin>";
			imagefd = 0;
		} else {
			imagefile = argv[1];
			if ((imagefd = open(argv[1], O_RDONLY)) < 0) {
				fprintf(stderr, "Couldn't open image file: %s!\n", imagefile);
				exit(1);
			}
		}

		if (!mtd_check(device)) {
			fprintf(stderr, "Can't open device for writing!\n");
			exit(1);
		}
		/* check trx file before erasing or writing anything */
		if (!image_check(imagefd, device) && !force) {
			fprintf(stderr, "Image check failed.\n");
			exit(1);
		}
	} else if ((strcmp(argv[0], "jffs2write") == 0) && (argc == 3)) {
		cmd = CMD_JFFS2WRITE;
		device = argv[2];

		imagefile = argv[1];
		if (!mtd_check(device)) {
			fprintf(stderr, "Can't open device for writing!\n");
			exit(1);
		}
	} else {
		usage();
	}

	sync();

	i = 0;
	unlocked = 0;
	while (erase[i] != NULL) {
		mtd_unlock(erase[i]);
		mtd_erase(erase[i]);
		if (strcmp(erase[i], device) == 0)
			unlocked = 1;
		i++;
	}

	switch (cmd) {
		case CMD_UNLOCK:
			if (!unlocked)
				mtd_unlock(device);
			break;
		case CMD_VERIFY:
			mtd_verify(device, imagefile);
			break;
		case CMD_DUMP:
			mtd_dump(device, offset, dump_len);
			break;
		case CMD_ERASE:
			if (!unlocked)
				mtd_unlock(device);
			mtd_erase(device);
			break;
		case CMD_WRITE:
			if (!unlocked)
				mtd_unlock(device);
			mtd_write(imagefd, device, fis_layout, part_offset);
			break;
		case CMD_JFFS2WRITE:
			if (!unlocked)
				mtd_unlock(device);
			mtd_write_jffs2(device, imagefile, jffs2dir);
			break;
		case CMD_FIXTRX:
		    if (mtd_fixtrx) {
			    mtd_fixtrx(device, offset);
            }
		case CMD_FIXSEAMA:
			if (mtd_fixseama)
			    mtd_fixseama(device, 0);
			break;
	}

	sync();

	if (boot)
		do_reboot();

	return 0;
}
Exemple #6
0
void start_jffs2(void)
{
	if (!nvram_match("jffs2_on", "1")) {
		notice_set("jffs", "");
		return;
	}

	int format = 0;
	char s[256];
	int size;
	int part;
	const char *p;
	struct statfs sf;
	int model = 0;
	int i = 0;

        while(1) {
		if (wait_action_idle(10)) break;
		else i++;

		if(i>=10) {
			_dprintf("Mount jffs2 failed!");
			return;
		}
	}

	if (!mtd_getinfo(JFFS2_PARTITION, &part, &size)) return;

	model = get_model();
	_dprintf("start jffs2: %d, %d\n", part, size);
	if (nvram_match("jffs2_format", "1")) {
		nvram_set("jffs2_format", "0");
		nvram_commit_x();
		if (!mtd_erase(JFFS_NAME)) {
			error("formatting");
			return;
		}
		format = 1;
	}

	sprintf(s, "%d", size);
	p = nvram_get("jffs2_size");
	if ((p == NULL) || (strcmp(p, s) != 0)) {
		if (format) {
			nvram_set("jffs2_size", s);
			nvram_commit_x();
		}
		else if ((p != NULL) && (*p != 0)) {
			error("verifying known size of");
			return;
		}
	}

	if (statfs("/jffs", &sf) == 0) { 
		switch(model) {
			case MODEL_RTAC56S: 
			case MODEL_RTAC56U: 
			case MODEL_RTAC3200:
			case MODEL_DSLAC68U:
			case MODEL_RPAC68U: 
			case MODEL_RTAC68U: 
			case MODEL_RTAC87U:
			case MODEL_RTN18U: 
			case MODEL_RTN65U:
			case MODEL_RTN14U: // it should be better to use LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,6,36)
			{
				if (sf.f_type != 0x73717368 /* squashfs */) {
					// already mounted
					notice_set("jffs", format ? "Formatted" : "Loaded");
					return;
				}
				break;
			}
			default:
			{
	                        if (sf.f_type != 0x71736873 /* squashfs */) {
        	                        // already mounted
                	                notice_set("jffs", format ? "Formatted" : "Loaded");
                        	        return;
				}
				break;
			}
		}
	}

	if (nvram_get_int("jffs2_clean_fs")) {
		if (!mtd_unlock(JFFS2_PARTITION)) {
			error("unlocking");
			return;
		}
	}
	modprobe(JFFS_NAME);
	sprintf(s, MTD_BLKDEV(%d), part);

	if (mount(s, "/jffs", JFFS_NAME, MS_NOATIME, "") != 0) {
		if (!mtd_erase(JFFS_NAME)) {
                        error("formatting");
                        return;
                }

		format = 1;
		if (mount(s, "/jffs", JFFS_NAME, MS_NOATIME, "") != 0) {
			_dprintf("*** jffs2 2-nd mount error\n");
			//modprobe_r(JFFS_NAME);
			error("mounting");
			return;
		}
	}

#ifdef TEST_INTEGRITY
	int test;

	if (format) {
		if (f_write("/jffs/.tomato_do_not_erase", &size, sizeof(size), 0, 0) != sizeof(size)) {
			stop_jffs2(0);
			error("setting integrity test for");
			return;
		}
	}
	if ((f_read("/jffs/.tomato_do_not_erase", &test, sizeof(test)) != sizeof(test)) || (test != size)) {
		stop_jffs2(0);
		error("testing integrity of");
		return;
	}
#endif

	if (nvram_get_int("jffs2_clean_fs")) {
		_dprintf("Clean /jffs/*\n");
		system("rm -fr /jffs/*");
		nvram_unset("jffs2_clean_fs");
		nvram_commit_x();
	}

	notice_set("jffs", format ? "Formatted" : "Loaded");

	if (((p = nvram_get("jffs2_exec")) != NULL) && (*p != 0)) {
		chdir("/jffs");
		system(p);
		chdir("/");
	}
	run_userfile("/jffs", ".asusrouter", "/jffs", 3);

	if (!check_if_dir_exist("/jffs/scripts/")) mkdir("/jffs/scripts/", 0755);
	if (!check_if_dir_exist("/jffs/configs/")) mkdir("/jffs/configs/", 0755);
}
Exemple #7
0
void format_mount_2nd_jffs2(void)
{
        int format = 0;
        char s[256];
        int size;
        int part;
        const char *p;
        struct statfs sf;
        int model = 0;

        if (!wait_action_idle(10)) return;

        if (!mtd_getinfo(SECOND_JFFS2_PARTITION, &part, &size)) return;
	_dprintf("Format 2nd jffs2: %d, %d\n", part, size);

        model = get_model();

        sprintf(s, "%d", size);
        if (statfs(SECOND_JFFS2_PATH, &sf) == 0) {
                switch(model) {
                        case MODEL_RTAC56S:
                        case MODEL_RTAC56U:
			case MODEL_RTAC3200:
                        case MODEL_DSLAC68U:
                        case MODEL_RPAC68U:
                        case MODEL_RTAC68U:
                        case MODEL_RTAC87U:
			case MODEL_RTN18U:
                        case MODEL_RTN65U:
                        case MODEL_RTN14U: // it should be better to use LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,6,36)
                        {
                                if (sf.f_type != 0x73717368 /* squashfs */) {
                                        // already mounted
                                        notice_set("2nd_jffs", format ? "Formatted" : "Loaded");
                                        return;
                                }
                                break;
                        }
                        default:
                        {
                                if (sf.f_type != 0x71736873 /* squashfs */) {
                                        // already mounted
                                        notice_set("2nd_jffs", format ? "Formatted" : "Loaded");
                                        return;
                                }
                                break;
                        }
                }
        }

        if (!mtd_unlock(SECOND_JFFS2_PARTITION)) {
                error("unlocking");
                return;
        }

        modprobe(JFFS_NAME);
        sprintf(s, MTD_BLKDEV(%d), part);
        if (mount(s, SECOND_JFFS2_PATH, JFFS_NAME, MS_NOATIME, "") != 0) {
		if( (get_model()==MODEL_RTAC56U || get_model()==MODEL_RTAC56S || get_model()==MODEL_RTAC3200 || get_model()==MODEL_RTAC68U || get_model()==MODEL_RPAC68U || get_model()==MODEL_DSLAC68U || get_model()==MODEL_RTAC87U || get_model()==MODEL_RTN18U) ^ (!mtd_erase(JFFS_NAME)) ){
                        error("formatting");
                        return;
                }

                format = 1;
                if (mount(s, SECOND_JFFS2_PATH, JFFS_NAME, MS_NOATIME, "") != 0) {
                        _dprintf("*** jffs2 2-nd mount error\n");
                        //modprobe_r(JFFS_NAME);
                        error("mounting");
                        return;
                }
        }

	sprintf(s, "rm -rf %s/*", SECOND_JFFS2_PATH);
        system(s);

        notice_set("2nd_jffs", format ? "Formatted" : "Loaded");

        if (((p = nvram_get("jffs2_exec")) != NULL) && (*p != 0)) {
                chdir(SECOND_JFFS2_PATH);
                system(p);
                chdir("/");
        }
        run_userfile(SECOND_JFFS2_PATH, ".asusrouter", SECOND_JFFS2_PATH, 3);

}
Exemple #8
0
static int flash_erase(int mtdnum)
{
	int fd;
	char mtd_device[LINESIZE];
	struct mtd_dev_info *mtd;
	int noskipbad = 0;
	int unlock = 0;
	unsigned int eb, eb_start, eb_cnt;
	struct flash_description *flash = get_flash_info();

	if  (!mtd_dev_present(flash->libmtd, mtdnum)) {
			ERROR("MTD %d does not exist\n", mtdnum);
			return -ENODEV;
	}
	mtd = &flash->mtd_info[mtdnum].mtd;
	snprintf(mtd_device, sizeof(mtd_device), "/dev/mtd%d", mtdnum);

	if ((fd = open(mtd_device, O_RDWR)) < 0) {
		ERROR( "%s: %s: %s", __func__, mtd_device, strerror(errno));
		return -ENODEV;
	}

	/*
	 * prepare to erase all of the MTD partition,
	 */
	eb_start = 0;
	eb_cnt = (mtd->size / mtd->eb_size) - eb_start;
	for (eb = 0; eb < eb_start + eb_cnt; eb++) {

		/* Always skip bad sectors */
		if (!noskipbad) {
			int ret = mtd_is_bad(mtd, fd, eb);
			if (ret > 0) {
				continue;
			} else if (ret < 0) {
				if (errno == EOPNOTSUPP) {
					noskipbad = 1;
				} else {
					ERROR("%s: MTD get bad block failed", mtd_device);
					return -EFAULT;
				}
			}
		}

		if (unlock) {
			if (mtd_unlock(mtd, fd, eb) != 0) {
				TRACE("%s: MTD unlock failure", mtd_device);
				continue;
			}
		}

		if (mtd_erase(flash->libmtd, mtd, fd, eb) != 0) {
			ERROR("%s: MTD Erase failure", mtd_device);
			return -EFAULT;
		}
	}

	close(fd);

	return 0;
}
Exemple #9
0
int main (int argc, char **argv)
{
	int ch, i, boot, unlock, imagefd, unlocked, offset, len;
	char *erase[MAX_ARGS], *device, *imagefile, *tmp;
	enum {
		CMD_ERASE,
		CMD_WRITE,
		CMD_UNLOCK
	} cmd;
	
	erase[0] = NULL;
	boot = 0;
	buflen = 0;
	quiet = 0;
	verbose = 0;
	offset = 0;
	len = 0;

	while ((ch = getopt(argc, argv, "vwrqe:o:l:")) != -1)
		switch (ch) {
			case 'r':
				boot = 1;
				break;
			case 'q':
				quiet++;
				break;
			case 'e':
				i = 0;
				while ((erase[i] != NULL) && ((i + 1) < MAX_ARGS))
					i++;
					
				erase[i++] = optarg;
				erase[i] = NULL;
				break;
			case 'v':
				verbose++;
				break;
			case 'o':
				offset = atoi(optarg);
				break;
			case 'l':
				len = atoi(optarg);
				break;
			case 'w':
				write_check++;
				break;
			case '?':
			default:
				usage();
		}
	argc -= optind;
	argv += optind;
	
	if (argc < 2)
		usage();

	if(len == 0){
		len = getFileSize(argv[1]);
	}

	if ((strcmp(argv[0], "unlock") == 0) && (argc == 2)) {
		cmd = CMD_UNLOCK;
		device = argv[1];
	} else if ((strcmp(argv[0], "erase") == 0) && (argc == 2)) {
		cmd = CMD_ERASE;
		device = argv[1];
	} else if ((strcmp(argv[0], "write") == 0) && (argc == 3)) {
		cmd = CMD_WRITE;
		device = argv[2];
	
		if (strcmp(argv[1], "-") == 0) {
			imagefile = "<stdin>";
			imagefd = 0;
		} else {
			imagefile = argv[1];
			if ((imagefd = open(argv[1], O_RDONLY)) < 0) {
				fprintf(stderr, "Couldn't open image file: %s!\n", imagefile);
				exit(1);
			}
		}
	
		if (!mtd_check(device)) {
			fprintf(stderr, "Can't open device for writing!\n");
			exit(1);
		}
	} else {
		usage();
	}

	sync();
	
	i = 0;
	unlocked = 0;
	while (erase[i] != NULL) {
		if (quiet < 2)
			fprintf(stderr, "Unlocking %s ...\n", erase[i]);
		mtd_unlock(erase[i]);
		if (quiet < 2)
			fprintf(stderr, "Erasing %s ...\n", erase[i]);
		mtd_erase(erase[i]);
		if (strcmp(erase[i], device) == 0)
			unlocked = 1;
		i++;
	}
	
	if (!unlocked) {
		if (quiet < 2) 
			fprintf(stderr, "Unlocking %s ...\n", device);
		mtd_unlock(device);
	}
		
	switch (cmd) {
		case CMD_UNLOCK:
			break;
		case CMD_ERASE:
			if (quiet < 2)
				fprintf(stderr, "Erasing %s ...\n", device);
			mtd_erase(device);
			break;
		case CMD_WRITE:
			if (quiet < 2)
				fprintf(stderr, "Writing from %s to %s ... ", imagefile, device);
			mtd_write(imagefd, offset, len,  device);
#if 0 //def CONFIG_DUAL_IMAGE
			if (!strcmp(device, "Kernel")) {
				printf("Reset stable flag and try coutner.\n");
				system("nvram_set uboot Image1Stable 0");
				system("nvram_set uboot Image1Try 0");
			}
#endif

			if (quiet < 2)
				fprintf(stderr, "\n");
			break;
	}

	sync();
	
	if (boot) {
		fflush(stdout);
		syscall(SYS_reboot,LINUX_REBOOT_MAGIC1,LINUX_REBOOT_MAGIC2,LINUX_REBOOT_CMD_RESTART,NULL);
	}
	return 0;
}
Exemple #10
0
void start_jffs2(void)
{
	if (!nvram_match("jffs2_on", "1")) {
		notice_set("jffs", "");
		return;
	}

	int format = 0;
	char s[256];
	int size;
	int part;
	const char *p;
	struct statfs sf;

	if (!wait_action_idle(10)) return;

	if (!mtd_getinfo("jffs2", &part, &size)) return;

_dprintf("*** jffs2: %d, %d\n", part, size);
	if (nvram_match("jffs2_format", "1")) {
		nvram_set("jffs2_format", "0");

		if (!mtd_erase("jffs2")) {
			error("formatting");
			return;
		}

		format = 1;
	}

	sprintf(s, "%d", size);
	p = nvram_get("jffs2_size");
	if ((p == NULL) || (strcmp(p, s) != 0)) {
		if (format) {
			nvram_set("jffs2_size", s);
			nvram_commit_x();
		}
		else if ((p != NULL) && (*p != 0)) {
			error("verifying known size of");
			return;
		}
	}

	if ((statfs("/jffs", &sf) == 0) && (sf.f_type != 0x71736873 /* squashfs */)) {
		// already mounted
		notice_set("jffs", format ? "Formatted" : "Loaded");
		return;
	}
	if (!mtd_unlock("jffs2")) {
		error("unlocking");
		return;
	}
	modprobe(JFFS_NAME);
	sprintf(s, MTD_BLKDEV(%d), part);
	if (mount(s, "/jffs", JFFS_NAME, MS_NOATIME, "") != 0) {
_dprintf("*** jffs2 mount error\n");
		//modprobe_r(JFFS_NAME);
		error("mounting");
		return;
	}
#ifdef TEST_INTEGRITY
	int test;

	if (format) {
		if (f_write("/jffs/.tomato_do_not_erase", &size, sizeof(size), 0, 0) != sizeof(size)) {
			stop_jffs2();
			error("setting integrity test for");
			return;
		}
	}
	if ((f_read("/jffs/.tomato_do_not_erase", &test, sizeof(test)) != sizeof(test)) || (test != size)) {
		stop_jffs2();
		error("testing integrity of");
		return;
	}
#endif

	notice_set("jffs", format ? "Formatted" : "Loaded");

	if (((p = nvram_get("jffs2_exec")) != NULL) && (*p != 0)) {
		chdir("/jffs");
		system(p);
		chdir("/");
	}
	run_userfile("/jffs", ".asusrouter", "/jffs", 3);

	if (!check_if_dir_exist("/jffs/scripts/")) mkdir("/jffs/scripts/", 0755);
	if (!check_if_dir_exist("/jffs/configs/")) mkdir("/jffs/configs/", 0755);

}
Exemple #11
0
int main (int argc, char **argv)
{
	int ch, i, boot, imagefd = 0, force, unlocked;
	char *erase[MAX_ARGS], *device = NULL;
	enum {
		CMD_ERASE,
		CMD_WRITE,
		CMD_UNLOCK,
		CMD_REFRESH,
		CMD_JFFS2WRITE
	} cmd = -1;
	
	erase[0] = NULL;
	boot = 0;
	force = 0;
	buflen = 0;
	quiet = 0;

	while ((ch = getopt(argc, argv, "frqe:d:j:")) != -1)
		switch (ch) {
			case 'f':
				force = 1;
				break;
			case 'r':
				boot = 1;
				break;
			case 'j':
				jffs2file = optarg;
				break;
			case 'q':
				quiet++;
				break;
			case 'e':
				i = 0;
				while ((erase[i] != NULL) && ((i + 1) < MAX_ARGS))
					i++;
					
				erase[i++] = optarg;
				erase[i] = NULL;
				break;
			case 'd':
				jffs2dir = optarg;
				break;
			case '?':
			default:
				usage();
		}
	argc -= optind;
	argv += optind;
	
	if (argc < 2)
		usage();

	if ((strcmp(argv[0], "unlock") == 0) && (argc == 2)) {
		cmd = CMD_UNLOCK;
		device = argv[1];
	} else if ((strcmp(argv[0], "refresh") == 0) && (argc == 2)) {
		cmd = CMD_REFRESH;
		device = argv[1];
	} else if ((strcmp(argv[0], "erase") == 0) && (argc == 2)) {
		cmd = CMD_ERASE;
		device = argv[1];
	} else if ((strcmp(argv[0], "write") == 0) && (argc == 3)) {
		cmd = CMD_WRITE;
		device = argv[2];
	
		if (strcmp(argv[1], "-") == 0) {
			imagefile = "<stdin>";
			imagefd = 0;
		} else {
			imagefile = argv[1];
			if ((imagefd = open(argv[1], O_RDONLY)) < 0) {
				fprintf(stderr, "Couldn't open image file: %s!\n", imagefile);
				exit(1);
			}
		}
	
		if (!mtd_check(device)) {
			fprintf(stderr, "Can't open device for writing!\n");
			exit(1);
		}
		/* check trx file before erasing or writing anything */
		if (!image_check(imagefd, device) && !force) {
			fprintf(stderr, "Image check failed.\n");
			exit(1);
		}
	} else if ((strcmp(argv[0], "jffs2write") == 0) && (argc == 3)) {
		cmd = CMD_JFFS2WRITE;
		device = argv[2];
	
		imagefile = argv[1];
		if (!mtd_check(device)) {
			fprintf(stderr, "Can't open device for writing!\n");
			exit(1);
		}
	} else {
		usage();
	}

	sync();
	
	i = 0;
	unlocked = 0;
	while (erase[i] != NULL) {
		mtd_unlock(erase[i]);
		mtd_erase(erase[i]);
		if (strcmp(erase[i], device) == 0)
			unlocked = 1;
		i++;
	}
	
		
	switch (cmd) {
		case CMD_UNLOCK:
			if (!unlocked)
				mtd_unlock(device);
			break;
		case CMD_ERASE:
			if (!unlocked)
				mtd_unlock(device);
			mtd_erase(device);
			break;
		case CMD_WRITE:
			if (!unlocked)
				mtd_unlock(device);
			mtd_write(imagefd, device);
			break;
		case CMD_JFFS2WRITE:
			if (!unlocked)
				mtd_unlock(device);
			mtd_write_jffs2(device, imagefile, jffs2dir);
			break;
		case CMD_REFRESH:
			mtd_refresh(device);
			break;
	}

	sync();
	
	if (boot)
		do_reboot();

	return 0;
}
Exemple #12
0
int mtd_main(int argc, char **argv)
{
	int ch, i, boot, unlock, imagefd, force, quiet, unlocked;
	char *erase[MAX_ARGS], *device, *imagefile;
	enum {
		CMD_ERASE,
		CMD_WRITE,
		CMD_UNLOCK
	} cmd;

	erase[0] = NULL;
	boot = 0;
	force = 0;
	buflen = 0;
	quiet = 0;

	while ((ch = getopt(argc, argv, "frqe:")) != -1)
		switch (ch) {
		case 'f':
			force = 1;
			break;
		case 'r':
			boot = 1;
			break;
		case 'q':
			quiet++;
			break;
		case 'e':
			i = 0;
			while ((erase[i] != NULL) && ((i + 1) < MAX_ARGS))
				i++;

			erase[i++] = optarg;
			erase[i] = NULL;
			break;

		case '?':
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

	if (argc < 2)
		usage();

	if ((strcmp(argv[0], "unlock") == 0) && (argc == 2)) {
		cmd = CMD_UNLOCK;
		device = argv[1];
	} else if ((strcmp(argv[0], "erase") == 0) && (argc == 2)) {
		cmd = CMD_ERASE;
		device = argv[1];
	} else if ((strcmp(argv[0], "write") == 0) && (argc == 3)) {
		cmd = CMD_WRITE;
		device = argv[2];

		if (strcmp(argv[1], "-") == 0) {
			imagefile = "<stdin>";
			imagefd = 0;
		} else {
			imagefile = argv[1];
			if ((imagefd = open(argv[1], O_RDONLY)) < 0) {
				fprintf(stderr,
					"Couldn't open image file: %s!\n",
					imagefile);
				exit(1);
			}
		}

		/* 
		 * check trx file before erasing or writing anything 
		 */
		if (!image_check(imagefd, device)) {
			if ((quiet < 2) || !force)
				fprintf(stderr, "TRX check failed!\n");
			if (!force)
				exit(1);
		} else {
			if (!mtd_check(device)) {
				fprintf(stderr,
					"Can't open device for writing!\n");
				exit(1);
			}
		}
	} else {
		usage();
	}

	sync();

	i = 0;
	unlocked = 0;
	while (erase[i] != NULL) {
		if (quiet < 2)
			fprintf(stderr, "Unlocking %s ...\n", erase[i]);
		mtd_unlock(erase[i]);
		if (quiet < 2)
			fprintf(stderr, "Erasing %s ...\n", erase[i]);
		mtd_erase(erase[i]);
		if (strcmp(erase[i], device) == 0)
			unlocked = 1;
		i++;
	}

	if (!unlocked) {
		if (quiet < 2)
			fprintf(stderr, "Unlocking %s ...\n", device);
		mtd_unlock(device);
	}

	switch (cmd) {
	case CMD_UNLOCK:
		break;
	case CMD_ERASE:
		if (quiet < 2)
			fprintf(stderr, "Erasing %s ...\n", device);
		mtd_erase(device);
		break;
	case CMD_WRITE:
		if (quiet < 2)
			fprintf(stderr, "Writing from %s to %s ... ", imagefile,
				device);
		mtd_write(imagefd, device, quiet);
		if (quiet < 2)
			fprintf(stderr, "\n");
		break;
	}

	sync();

	if (boot)
		kill(1, 15);	// send SIGTERM to init for reboot

	return 0;
}
Exemple #13
0
static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
	struct mtd_part *part = PART(mtd);
	return mtd_unlock(part->master, ofs + part->offset, len);
}
Exemple #14
0
void start_jffs2(void)
{
	if (!nvram_match("jffs2_enable", "1")) {
		notice_set("jffs", "");
		return;
	}

	int format = 0;
	char s[256];
	int size;
	int part;
	const char *p;
	int model = 0;
	int i = 0;

        while(1) {
		if (wait_action_idle(10)) break;
		else i++;

		if(i>=10) {
			_dprintf("Mount jffs2 failed!");
			return;
		}
	}

	if (!mtd_getinfo(JFFS2_PARTITION, &part, &size)) return;

	model = get_model();
	_dprintf("start jffs2: %d, %d\n", part, size);
	if (nvram_match("jffs2_format", "1")) {
		nvram_set("jffs2_format", "0");
		nvram_commit_x();
		if (mtd_erase(JFFS2_MTD_NAME)) {
			error("formatting");
			return;
		}
		format = 1;
	}

	sprintf(s, "%d", size);
	p = nvram_get("jffs2_size");
	if ((p == NULL) || (strcmp(p, s) != 0)) {
		if (format) {
			nvram_set("jffs2_size", s);
			nvram_commit_x();
		}
		else if ((p != NULL) && (*p != 0)) {
			error("verifying known size of");
			return;
		}
	}

	if(!check_in_rootfs("/jffs", "jffs", format))
		return;

	if (nvram_get_int("jffs2_clean_fs")) {
		if (!mtd_unlock(JFFS2_PARTITION)) {
			error("unlocking");
			return;
		}
	}
	modprobe(JFFS_NAME);
	sprintf(s, MTD_BLKDEV(%d), part);

	if (mount(s, "/jffs", JFFS_NAME, MS_NOATIME, "") != 0) {
		if (mtd_erase(JFFS2_MTD_NAME)) {
			jffs2_fail = 1;
                        error("formatting");
                        return;
                }

		format = 1;
		if (mount(s, "/jffs", JFFS_NAME, MS_NOATIME, "") != 0) {
			_dprintf("*** jffs2 2-nd mount error\n");
			//modprobe_r(JFFS_NAME);
			error("mounting");
			jffs2_fail = 1;
			return;
		}
	}

	if(nvram_match("force_erase_jffs2", "1")) {
		_dprintf("\n*** force erase jffs2 ***\n");
		mtd_erase(JFFS2_MTD_NAME);
		nvram_set("jffs2_clean_fs", "1");
		nvram_commit();
		reboot(RB_AUTOBOOT);
	}
#ifdef TEST_INTEGRITY
	int test;

	if (format) {
		if (f_write("/jffs/.tomato_do_not_erase", &size, sizeof(size), 0, 0) != sizeof(size)) {
			stop_jffs2(0);
			error("setting integrity test for");
			return;
		}
	}
	if ((f_read("/jffs/.tomato_do_not_erase", &test, sizeof(test)) != sizeof(test)) || (test != size)) {
		stop_jffs2(0);
		error("testing integrity of");
		return;
	}
#endif

	if (nvram_get_int("jffs2_clean_fs")) {
		_dprintf("Clean /jffs/*\n");
		system("rm -fr /jffs/*");
		nvram_unset("jffs2_clean_fs");
		nvram_commit_x();
	}

	notice_set("jffs", format ? "Formatted" : "Loaded");
	jffs2_fail = 0;

	if (((p = nvram_get("jffs2_exec")) != NULL) && (*p != 0)) {
		chdir("/jffs");
		system(p);
		chdir("/");
	}
	run_userfile("/jffs", ".asusrouter", "/jffs", 3);

	if (!check_if_dir_exist("/jffs/scripts/")) mkdir("/jffs/scripts/", 0755);
	if (!check_if_dir_exist("/jffs/configs/")) mkdir("/jffs/configs/", 0755);
}
Exemple #15
0
int main(int argc, char *argv[])
{
	libmtd_t mtd_desc;
	struct mtd_dev_info mtd;
	int fd, clmpos = 0, clmlen = 8;
	unsigned long long start;
	unsigned int eb, eb_start, eb_cnt;
	int isNAND;
	int error = 0;
	off_t offset = 0;

	/*
	 * Process user arguments
	 */
	for (;;) {
		int option_index = 0;
		static const char *short_options = "jNqu";
		static const struct option long_options[] = {
			{"help", no_argument, 0, 0},
			{"version", no_argument, 0, 0},
			{"jffs2", no_argument, 0, 'j'},
			{"noskipbad", no_argument, 0, 'N'},
			{"quiet", no_argument, 0, 'q'},
			{"silent", no_argument, 0, 'q'},
			{"unlock", no_argument, 0, 'u'},

			{0, 0, 0, 0},
		};

		int c = getopt_long(argc, argv, short_options,
				long_options, &option_index);
		if (c == EOF)
			break;

		switch (c) {
		case 0:
			switch (option_index) {
			case 0:
				display_help();
				return 0;
			case 1:
				display_version();
				return 0;
			}
			break;
		case 'j':
			jffs2 = 1;
			break;
		case 'N':
			noskipbad = 1;
			break;
		case 'q':
			quiet = 1;
			break;
		case 'u':
			unlock = 1;
			break;
		case '?':
			error = 1;
			break;
		}
	}
	switch (argc - optind) {
	case 3:
		mtd_device = argv[optind];
		start = simple_strtoull(argv[optind + 1], &error);
		eb_cnt = simple_strtoul(argv[optind + 2], &error);
		break;
	default:
	case 0:
		errmsg("no MTD device specified");
	case 1:
		errmsg("no start erase block specified");
	case 2:
		errmsg("no erase block count specified");
		error = 1;
		break;
	}
	if (error)
		return errmsg("Try `--help' for more information");

	/*
	 * Locate MTD and prepare for erasure
	 */
	mtd_desc = libmtd_open();
	if (mtd_desc == NULL)
		return errmsg("can't initialize libmtd");

	if ((fd = open(mtd_device, O_RDWR)) < 0)
		return sys_errmsg("%s", mtd_device);

	if (mtd_get_dev_info(mtd_desc, mtd_device, &mtd) < 0)
		return errmsg("mtd_get_dev_info failed");

	eb_start = start / mtd.eb_size;

	isNAND = mtd.type == MTD_NANDFLASH ? 1 : 0;

	if (jffs2) {
		cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
		cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
		if (!isNAND)
			cleanmarker.totlen = cpu_to_je32(sizeof(cleanmarker));
		else {
			struct nand_oobinfo oobinfo;

			if (ioctl(fd, MEMGETOOBSEL, &oobinfo) != 0)
				return sys_errmsg("%s: unable to get NAND oobinfo", mtd_device);

			/* Check for autoplacement */
			if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
				/* Get the position of the free bytes */
				if (!oobinfo.oobfree[0][1])
					return errmsg(" Eeep. Autoplacement selected and no empty space in oob");
				clmpos = oobinfo.oobfree[0][0];
				clmlen = oobinfo.oobfree[0][1];
				if (clmlen > 8)
					clmlen = 8;
			} else {
				/* Legacy mode */
				switch (mtd.oob_size) {
					case 8:
						clmpos = 6;
						clmlen = 2;
						break;
					case 16:
						clmpos = 8;
						clmlen = 8;
						break;
					case 64:
						clmpos = 16;
						clmlen = 8;
						break;
				}
			}
			cleanmarker.totlen = cpu_to_je32(8);
		}
		cleanmarker.hdr_crc = cpu_to_je32(mtd_crc32(0, &cleanmarker, sizeof(cleanmarker) - 4));
	}

	/*
	 * Now do the actual erasing of the MTD device
	 */
	if (eb_cnt == 0)
		eb_cnt = (mtd.size / mtd.eb_size) - eb_start;

	for (eb = eb_start; eb < eb_start + eb_cnt; eb++) {
		offset = (off_t)eb * mtd.eb_size;

		if (!noskipbad) {
			int ret = mtd_is_bad(&mtd, fd, eb);
			if (ret > 0) {
				verbose(!quiet, "Skipping bad block at %08"PRIxoff_t, offset);
				continue;
			} else if (ret < 0) {
				if (errno == EOPNOTSUPP) {
					noskipbad = 1;
					if (isNAND)
						return errmsg("%s: Bad block check not available", mtd_device);
				} else
					return sys_errmsg("%s: MTD get bad block failed", mtd_device);
			}
		}

		show_progress(&mtd, offset, eb, eb_start, eb_cnt);

		if (unlock) {
			if (mtd_unlock(&mtd, fd, eb) != 0) {
				sys_errmsg("%s: MTD unlock failure", mtd_device);
				continue;
			}
		}

		if (mtd_erase(mtd_desc, &mtd, fd, eb) != 0) {
			sys_errmsg("%s: MTD Erase failure", mtd_device);
			continue;
		}

		/* format for JFFS2 ? */
		if (!jffs2)
			continue;

		/* write cleanmarker */
		if (isNAND) {
			if (mtd_write_oob(mtd_desc, &mtd, fd, (uint64_t)offset + clmpos, clmlen, &cleanmarker) != 0) {
				sys_errmsg("%s: MTD writeoob failure", mtd_device);
				continue;
			}
		} else {
			if (lseek(fd, offset, SEEK_SET) < 0) {
				sys_errmsg("%s: MTD lseek failure", mtd_device);
				continue;
			}
			if (write(fd, &cleanmarker, sizeof(cleanmarker)) != sizeof(cleanmarker)) {
				sys_errmsg("%s: MTD write failure", mtd_device);
				continue;
			}
		}
		verbose(!quiet, " Cleanmarker written at %"PRIxoff_t, offset);
	}
	show_progress(&mtd, offset, eb, eb_start, eb_cnt);
	bareverbose(!quiet, "\n");

	return 0;
}