+ }
+static int main_switch2jffs(int argc, char **argv)
+{
+ char mtd[32];
+ char *mp;
+ int ret = -1;
+
+ if (find_overlay_mount("overlayfs:/tmp/root"))
+ return -1;
+
+ if (check_fs_exists("overlay")) {
+ ERROR("overlayfs not found\n");
+ return ret;
+ }
+
+ find_mtd_block("rootfs_data", mtd, sizeof(mtd));
+ mp = find_mount_point(mtd, NULL);
+ if (mp) {
+ LOG("rootfs_data:%s is already mounted as %s\n", mtd, mp);
+ return -1;
+ }
+
+ if (find_mtd_char("rootfs_data", mtd, sizeof(mtd))) {
+ ERROR("no rootfs_data was found\n");
+ return ret;
+ }
+
+ switch (jffs2_ready(mtd)) {
+ case FS_NONE:
+ ERROR("no jffs2 marker found\n");
+ /* fall through */
+
+ case FS_DEADCODE:
+ ret = switch2jffs();
+ if (!ret) {
+ DEBUG(1, "doing fo cleanup\n");
+ umount2("/tmp/root", MNT_DETACH);
+ foreachdir("/overlay/", handle_whiteout);
+ }
+ break;
+
+ case FS_JFFS2:
+ ret = mtd_mount_jffs2();
+ if (ret)
+ break;
+ if (mount_move("/tmp", "", "/overlay") || fopivot("/overlay", "/rom")) {
+ ERROR("switching to jffs2 failed\n");
+ ret = -1;
+ }
+ break;
+ }
+
+ return ret;
+}
+
+static int extroot(const char *prefix)
+{
+ char block_path[32];
+ char kmod_loader[64];
+ struct stat s;
+ pid_t pid;
+
+ sprintf(block_path, "%s/sbin/block", prefix);
+
+ if (stat(block_path, &s))
+ return -1;
+
+ sprintf(kmod_loader, "/sbin/kmodloader %s/etc/modules-boot.d/ %s", prefix, prefix);
+ system(kmod_loader);
+
+ pid = fork();
+ if (!pid) {
+ mkdir("/tmp/extroot", 0755);
+ execl(block_path, block_path, "extroot", NULL);
+ exit(-1);
+ } else if (pid > 0) {
+ int status;
+
+ waitpid(pid, &status, 0);
+ if (!WEXITSTATUS(status)) {
+ if (find_mount("/tmp/extroot/mnt")) {
+ mount("/dev/root", "/", NULL, MS_NOATIME | MS_REMOUNT | MS_RDONLY, 0);
+
+ mkdir("/tmp/extroot/mnt/proc", 0755);
+ mkdir("/tmp/extroot/mnt/dev", 0755);
+ mkdir("/tmp/extroot/mnt/sys", 0755);
+ mkdir("/tmp/extroot/mnt/tmp", 0755);
+ mkdir("/tmp/extroot/mnt/rom", 0755);
+
+ if (mount_move("/tmp/extroot", "", "/mnt")) {
+ ERROR("moving pivotroot failed - continue normal boot\n");
+ umount("/tmp/extroot/mnt");
+ } else if (pivot("/mnt", "/rom")) {
+ ERROR("switching to pivotroot failed - continue normal boot\n");
+ umount("/mnt");
+ } else {
+ umount("/tmp/overlay");
+ rmdir("/tmp/overlay");
+ rmdir("/tmp/extroot/mnt");
+ rmdir("/tmp/extroot");
+ return 0;
+ }
+ } else if (find_mount("/tmp/extroot/overlay")) {
+ if (mount_move("/tmp/extroot", "", "/overlay")) {
+ ERROR("moving extroot failed - continue normal boot\n");
+ umount("/tmp/extroot/overlay");
+ } else if (fopivot("/overlay", "/rom")) {
+ ERROR("switching to extroot failed - continue normal boot\n");
+ umount("/overlay");
+ } else {
+ umount("/tmp/overlay");
+ rmdir("/tmp/overlay");
+ rmdir("/tmp/extroot/overlay");
+ rmdir("/tmp/extroot");
+ return 0;
+ }
+ }
+ }
+ }
+ return -1;