kmodloader: use the name of the module struct when unloading modules
[project/ubox.git] / mount_root.c
index ad1de36..f1474f0 100644 (file)
@@ -490,6 +490,139 @@ static int handle_whiteout(const char *dir)
        return 0;
 }
 
+static int mtd_erase(const char *mtd)
+{
+       int fd = open(mtd, O_RDWR | O_SYNC);
+       struct mtd_info_user i;
+       struct erase_info_user e;
+       int ret;
+
+       if (!fd) {
+               ERROR("failed to open %s: %s\n", mtd, strerror(errno));
+               return -1;
+       }
+
+       ret = ioctl(fd, MEMGETINFO, &i);
+       if (ret) {
+               ERROR("ioctl(%s, MEMGETINFO) failed: %s\n", mtd, strerror(errno));
+               return -1;
+       }
+
+       e.length = i.erasesize;
+       for (e.start = 0; e.start < i.size; e.start += i.erasesize) {
+               ioctl(fd, MEMUNLOCK, &e);
+               if(ioctl(fd, MEMERASE, &e))
+                       ERROR("Failed to erase block on %s at 0x%x\n", mtd, e.start);
+       }
+
+       close(fd);
+       return 0;
+}
+
+static int ask_user(int argc, char **argv)
+{
+       if ((argc < 2) || strcmp(argv[1], "-y")) {
+               LOG("This will erase all settings and remove any installed packages. Are you sure? [N/y]\n");
+               if (getchar() != 'y')
+                       return -1;
+       }
+       return 0;
+
+}
+
+static int handle_rmdir(const char *dir)
+{
+       struct stat s;
+       struct dirent **namelist;
+       int n;
+
+       n = scandir(dir, &namelist, NULL, NULL);
+
+       if (n < 1)
+               return -1;
+
+       while (n--) {
+               char file[256];
+
+               snprintf(file, sizeof(file), "%s%s", dir, namelist[n]->d_name);
+               if (!lstat(file, &s) && !S_ISDIR(s.st_mode)) {
+                       DEBUG(1, "unlinking %s\n", file);
+                       unlink(file);
+               }
+               free(namelist[n]);
+       }
+       free(namelist);
+
+       DEBUG(1, "rmdir %s\n", dir);
+       rmdir(dir);
+
+       return 0;
+}
+
+static int main_jffs2reset(int argc, char **argv)
+{
+       char mtd[32];
+       char *mp;
+
+       if (ask_user(argc, argv))
+               return -1;
+
+       if (check_fs_exists("overlay")) {
+               ERROR("overlayfs not found\n");
+               return -1;
+       }
+
+       if (find_mtd_block("rootfs_data", mtd, sizeof(mtd))) {
+               ERROR("no rootfs_data was found\n");
+               return -1;
+       }
+
+       mp = find_mount_point(mtd, "jffs2");
+       if (mp) {
+               LOG("%s is mounted as %s, only ereasing files\n", mtd, mp);
+               foreachdir(mp, handle_rmdir);
+               mount(mp, "/", NULL, MS_REMOUNT, 0);
+       } else {
+               LOG("%s is not mounted, erasing it\n", mtd);
+               find_mtd_char("rootfs_data", mtd, sizeof(mtd));
+               mtd_erase(mtd);
+       }
+
+       return 0;
+}
+
+static int main_jffs2mark(int argc, char **argv)
+{
+       FILE *fp;
+       __u32 deadc0de = __cpu_to_be32(0xdeadc0de);
+       char mtd[32];
+       size_t sz;
+
+       if (ask_user(argc, argv))
+               return -1;
+
+       if (find_mtd_block("rootfs_data", mtd, sizeof(mtd))) {
+               ERROR("no rootfs_data was found\n");
+               return -1;
+       }
+
+       fp = fopen(mtd, "w");
+       LOG("%s - marking with deadc0de\n", mtd);
+       if (!fp) {
+               ERROR("opening %s failed\n", mtd);
+               return -1;
+       }
+
+       sz = fwrite(&deadc0de, sizeof(deadc0de), 1, fp);
+       fclose(fp);
+
+       if (sz != 1) {
+               ERROR("writing %s failed: %s\n", mtd, strerror(errno));
+               return -1;
+       }
+
+       return 0;
+ }
 static int main_switch2jffs(int argc, char **argv)
 {
        char mtd[32];
@@ -544,50 +677,65 @@ static int main_switch2jffs(int argc, char **argv)
        return ret;
 }
 
-static int extroot(void)
+static int extroot(const char *prefix)
 {
+       char block_path[32];
+       char kmod_loader[64];
        struct stat s;
        pid_t pid;
 
-       if (stat("/sbin/block", &s))
+       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("/sbin/block", "/sbin/block", "extroot", NULL);
+               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/mnt")) {
+                       if (find_mount("/tmp/extroot/mnt")) {
                                mount("/dev/root", "/", NULL, MS_NOATIME | MS_REMOUNT | MS_RDONLY, 0);
 
-                               mkdir("/tmp/mnt/proc", 0755);
-                               mkdir("/tmp/mnt/dev", 0755);
-                               mkdir("/tmp/mnt/sys", 0755);
-                               mkdir("/tmp/mnt/tmp", 0755);
-                               mkdir("/tmp/mnt/rom", 0755);
+                               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", "", "/mnt")) {
+                               if (mount_move("/tmp/extroot", "", "/mnt")) {
                                        ERROR("moving pivotroot failed - continue normal boot\n");
-                                       umount("/tmp/mnt");
+                                       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/overlay")) {
-                               if (mount_move("/tmp", "", "/overlay")) {
+                       } else if (find_mount("/tmp/extroot/overlay")) {
+                               if (mount_move("/tmp/extroot", "", "/overlay")) {
                                        ERROR("moving extroot failed - continue normal boot\n");
-                                       umount("/tmp/overlay");
+                                       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;
                                }
                        }
@@ -603,6 +751,12 @@ int main(int argc, char **argv)
 
        argv0 = basename(*argv);
 
+       if (!strcmp(basename(*argv), "jffs2mark"))
+               return main_jffs2mark(argc, argv);
+
+       if (!strcmp(basename(*argv), "jffs2reset"))
+               return main_jffs2reset(argc, argv);
+
        if (!strcmp(basename(*argv), "switch2jffs"))
                return main_switch2jffs(argc, argv);
 
@@ -615,7 +769,7 @@ int main(int argc, char **argv)
                LOG("mounting /dev/root\n");
                mount("/dev/root", "/", NULL, MS_NOATIME | MS_REMOUNT, 0);
        } else {
-               if (!extroot()) {
+               if (!extroot("")) {
                        fprintf(stderr, "mount_root: switched to extroot\n");
                        return 0;
                }
@@ -634,6 +788,12 @@ int main(int argc, char **argv)
                        }
 
                        mtd_mount_jffs2();
+
+                       if (!extroot("/tmp/overlay")) {
+                               fprintf(stderr, "mount_root: switched to extroot\n");
+                               return 0;
+                       }
+
                        DEBUG(1, "switching to jffs2\n");
                        if (mount_move("/tmp", "", "/overlay") || fopivot("/overlay", "/rom")) {
                                ERROR("switching to jffs2 failed - fallback to ramoverlay\n");