/* * Prepare the namespace - decide what/where to mount, load ramdisks, etc. */ void __init prepare_namespace(void) { int is_floppy; if (root_delay) { printk(KERN_INFO "Waiting %dsec before mounting root device...\n", root_delay); ssleep(root_delay); } /* * wait for the known devices to complete their probing * * Note: this is a potential source of long boot delays. * For example, it is not atypical to wait 5 seconds here * for the touchpad of a laptop to initialize. */ wait_for_device_probe(); md_run_setup(); if (saved_root_name[0]) { root_device_name = saved_root_name; printk(KERN_DEBUG "root_device_name: %s\n",root_device_name); if (!strncmp(root_device_name, "mtd", 3) || !strncmp(root_device_name, "ubi", 3)) { mount_block_root(root_device_name, root_mountflags); goto out; } ROOT_DEV = name_to_dev_t(root_device_name); if (strncmp(root_device_name, "/dev/", 5) == 0) root_device_name += 5; } if (initrd_load()) goto out; /* wait for any asynchronous scanning to complete */ if ((ROOT_DEV == 0) && root_wait) { printk(KERN_INFO "Waiting for root device %s...\n", saved_root_name); while (driver_probe_done() != 0 || (ROOT_DEV = name_to_dev_t(saved_root_name)) == 0) msleep(100); async_synchronize_full(); } is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; if (is_floppy && rd_doload && rd_load_disk(0)) ROOT_DEV = Root_RAM0; mount_root(); out: devtmpfs_mount("dev"); printk(KERN_DEBUG "after devtmpfs_mount\n"); sys_mount(".", "/", NULL, MS_MOVE, NULL); printk(KERN_DEBUG "after sys_mount\n"); sys_chroot((const char __user __force *)"."); }
/* * Prepare the namespace - decide what/where to mount, load ramdisks, etc. */ void __init prepare_namespace(void) { int is_floppy; if (root_delay) { printk(KERN_INFO "Waiting %dsec before mounting root device...\n", root_delay); ssleep(root_delay); } /* wait for the known devices to complete their probing */ while (driver_probe_done() != 0) msleep(100); md_run_setup(); if (saved_root_name[0]) { root_device_name = saved_root_name; if (!strncmp(root_device_name, "mtd", 3) || !strncmp(root_device_name, "ubi", 3) || !strncmp(root_device_name, "mmc", 3)) { mount_block_root(root_device_name, root_mountflags); goto out; } ROOT_DEV = name_to_dev_t(root_device_name); if (strncmp(root_device_name, "/dev/", 5) == 0) root_device_name += 5; } if (initrd_load()) goto out; /* wait for any asynchronous scanning to complete */ if ((ROOT_DEV == 0) && root_wait) { printk(KERN_INFO "Waiting for root device %s...\n", saved_root_name); while (driver_probe_done() != 0 || (ROOT_DEV = name_to_dev_t(saved_root_name)) == 0) msleep(100); } is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; if (is_floppy && rd_doload && rd_load_disk(0)) ROOT_DEV = Root_RAM0; mount_root(); out: sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot("."); security_sb_post_mountroot(); }
/* get_boot_dev is bassed on dm_get_device_by_uuid in dm_bootcache. */ static dev_t get_boot_dev(void) { const char partuuid[] = "PARTUUID="; char uuid[2 * sizeof(partuuid) + 36]; /* Room for 2 PARTUUIDs */ char *uuid_str; dev_t devt = 0; uuid_str = get_info_from_cmdline(" kern_guid=", &uuid[sizeof(partuuid) - 1], sizeof(uuid) - sizeof(partuuid)); if (!uuid_str) { DMERR("Couldn't get uuid, try root dev"); return 0; } if (strncmp(uuid_str, partuuid, strlen(partuuid)) != 0) { /* Not prefixed with "PARTUUID=", so add it */ memcpy(uuid, partuuid, sizeof(partuuid) - 1); uuid_str = uuid; } devt = name_to_dev_t(uuid_str); if (!devt) goto found_nothing; return devt; found_nothing: DMDEBUG("No matching partition for GUID: %s", uuid_str); return 0; }
static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { dev_t res; int len = n; char *name; if (len && buf[len-1] == '\n') len--; name = kstrndup(buf, len, GFP_KERNEL); if (!name) return -ENOMEM; res = name_to_dev_t(name); kfree(name); if (!res) return -EINVAL; lock_system_sleep(); swsusp_resume_device = res; unlock_system_sleep(); pr_info("Starting manual resume from disk\n"); noresume = 0; software_resume(); return n; }
/* * Prepare the namespace - decide what/where to mount, load ramdisks, etc. */ void __init prepare_namespace(void) { int is_floppy; mount_devfs(); md_run_setup(); if (saved_root_name[0]) { root_device_name = saved_root_name; ROOT_DEV = name_to_dev_t(root_device_name); if (strncmp(root_device_name, "/dev/", 5) == 0) root_device_name += 5; } is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; if (initrd_load()) goto out; if (is_floppy && rd_doload && rd_load_disk(0)) ROOT_DEV = Root_RAM0; mount_root(); out: umount_devfs("/dev"); sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot("."); security_sb_post_mountroot(); mount_devfs_fs (); }
static void __init dm_substitute_devices(char *str, size_t str_len) { char *candidate = str; char *candidate_end = str; char old_char; size_t len = 0; dev_t dev; if (str_len < 3) return; while (str && *str) { candidate = strchr(str, '/'); if (!candidate) break; /* Avoid embedded slashes */ if (candidate != str && *(candidate - 1) != DM_FIELD_SEP) { str = strchr(candidate, DM_FIELD_SEP); continue; } len = get_dm_option(candidate, &candidate_end, DM_FIELD_SEP); str = skip_spaces(candidate_end); if (len < 3 || len > 37) /* name_to_dev_t max; maj:mix min */ continue; /* Temporarily terminate with a nul */ candidate_end--; old_char = *candidate_end; *candidate_end = '\0'; DMDEBUG("converting candidate device '%s' to dev_t", candidate); /* Use the boot-time specific device naming */ dev = name_to_dev_t(candidate); *candidate_end = old_char; DMDEBUG(" -> %u", dev); /* No suitable replacement found */ if (!dev) continue; /* Rewrite the /dev/path as a major:minor */ len = snprintf(candidate, len, "%u:%u", MAJOR(dev), MINOR(dev)); if (!len) { DMERR("error substituting device major/minor."); break; } candidate += len; /* Pad out with spaces (fixing our nul) */ while (candidate < candidate_end) *(candidate++) = DM_FIELD_SEP; } }
static __init int start_module(void) { dev=name_to_dev_t(device); disk = get_gendisk(dev,&dummy); if(!disk) return 0; queue=disk->queue; getrawmonotonic(&init_time); block_fun=my_block_fun; block_requeue=my_block_requeue; block_comp=my_block_comp; return 0; }
static int read_suspend_image(const char * specialfile, int noresume) { union diskpage *cur; unsigned long scratch_page = 0; int error; char b[BDEVNAME_SIZE]; resume_device = name_to_dev_t(specialfile); scratch_page = get_zeroed_page(GFP_ATOMIC); cur = (void *) scratch_page; if (cur) { struct block_device *bdev; printk("Resuming from device %s\n", __bdevname(resume_device, b)); bdev = open_by_devnum(resume_device, FMODE_READ, BDEV_RAW); if (IS_ERR(bdev)) { error = PTR_ERR(bdev); } else { set_blocksize(bdev, PAGE_SIZE); error = __read_suspend_image(bdev, cur, noresume); blkdev_put(bdev, BDEV_RAW); } } else error = -ENOMEM; if (scratch_page) free_page(scratch_page); switch (error) { case 0: PRINTK("Reading resume file was successful\n"); break; case -EINVAL: break; case -EIO: printk( "%sI/O error\n", name_resume); break; case -ENOENT: printk( "%s%s: No such file or directory\n", name_resume, specialfile); break; case -ENOMEM: printk( "%sNot enough memory\n", name_resume); break; default: printk( "%sError %d resuming\n", name_resume, error ); } MDELAY(1000); return error; }
static ssize_t noresume_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { if (sscanf(buf, "%d", &noresume) == 1) { noresume = !!noresume; if (noresume) { if (!swsusp_resume_device) swsusp_resume_device = name_to_dev_t(resume_file); swsusp_check(); swsusp_close(FMODE_READ); } return n; } return -EINVAL; }
static __init int start_module(void) { dev=name_to_dev_t("/dev/sda1"); // dev_t dev1=blk_lookup_devt("sda",1); printk(KERN_INFO "Major %d minor %d\n",MAJOR(dev),MINOR(dev)); disk = get_gendisk(dev,&dummy); printk(KERN_INFO "disk name %s\n",disk->disk_name); if(!disk) return 0; simple_tsk = kthread_run(simple_thread, NULL, "event-sample"); if (IS_ERR(simple_tsk)) return -1; // while(1) // { // } // } /* buf = (unsigned char*)vmalloc(0x800); memset( buf , 0xFE , 0x800 ); bio = bio_map_kern( disk->queue , buf , 0x400 , GFP_KERNEL ); if( IS_ERR(bio) ) { vfree(buf); return 0; } bio->bi_sector = 0; bio->bi_bdev = bdget_disk(disk,0); printk(" bi_bdev = %016lX\n",(unsigned long)(bio->bi_bdev)); printk(" bi_bdev->bd_disk = %s\n",(bio->bi_bdev->bd_disk->disk_name)); if(bio->bi_sector) printk(" sector %lld \n",bio->bi_sector); if(bio->bi_flags) printk("flags %lu\n",bio->bi_flags); if(bio->bi_rw) printk("rw %lu\n",bio->bi_rw); */// queue=disk->queue; // req=queue->boundary_rq; //printk(KERN_INFO "Pending requests:%d\n",(queue->nr_pending)); return 0; }
int resume(const char *resume_file, unsigned long long resume_offset) { dev_t resume_device; int powerfd = -1; char device_string[64]; int len; resume_device = name_to_dev_t(resume_file); if (major(resume_device) == 0) { fprintf(stderr, "Invalid resume device: %s\n", resume_file); goto failure; } if ((powerfd = open("/sys/power/resume", O_WRONLY)) < 0) goto fail_r; len = snprintf(device_string, sizeof device_string, "%u:%u:%llu", major(resume_device), minor(resume_device), resume_offset); /* This should never happen */ if (len >= sizeof device_string) goto fail_r; dprintf("kinit: trying to resume from %s\n", resume_file); if (write(powerfd, device_string, len) != len) goto fail_r; /* Okay, what are we still doing alive... */ failure: if (powerfd >= 0) close(powerfd); dprintf("kinit: No resume image, doing normal boot...\n"); return -1; fail_r: fprintf(stderr, "Cannot write /sys/power/resume " "(no software suspend kernel support?)\n"); goto failure; }
int __init pmdisk_read(void) { int error; if (!strlen(resume_file)) return -ENOENT; resume_device = name_to_dev_t(resume_file); pr_debug("pmdisk: Resume From Partition: %s\n", resume_file); resume_bdev = open_by_devnum(resume_device, FMODE_READ); if (!IS_ERR(resume_bdev)) { set_blocksize(resume_bdev, PAGE_SIZE); error = read_suspend_image(); blkdev_put(resume_bdev); } else error = PTR_ERR(resume_bdev); if (!error) pr_debug("Reading resume file was successful\n"); else pr_debug("pmdisk: Error %d resuming\n", error); return error; }
static int __init mount_nfs_root(void) { char *root_dev, *root_data; unsigned int timeout; int try, err; err = nfs_root_data(&root_dev, &root_data); if (err != 0) return 0; /* * The server or network may not be ready, so try several * times. Stop after a few tries in case the client wants * to fall back to other boot methods. */ timeout = NFSROOT_TIMEOUT_MIN; for (try = 1; ; try++) { err = do_mount_root(root_dev, "nfs", root_mountflags, root_data); if (err == 0) return 1; if (try > NFSROOT_RETRY_MAX) break; /* Wait, in case the server refused us immediately */ ssleep(timeout); timeout <<= 1; if (timeout > NFSROOT_TIMEOUT_MAX) timeout = NFSROOT_TIMEOUT_MAX; } return 0; } #endif #if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD) void __init change_floppy(char *fmt, ...) { struct termios termios; char buf[80]; char c; int fd; va_list args; va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0); if (fd >= 0) { sys_ioctl(fd, FDEJECT, 0); sys_close(fd); } printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf); fd = sys_open("/dev/console", O_RDWR, 0); if (fd >= 0) { sys_ioctl(fd, TCGETS, (long)&termios); termios.c_lflag &= ~ICANON; sys_ioctl(fd, TCSETSF, (long)&termios); sys_read(fd, &c, 1); termios.c_lflag |= ICANON; sys_ioctl(fd, TCSETSF, (long)&termios); sys_close(fd); } } #endif void __init mount_root(void) { #ifdef CONFIG_ROOT_NFS if (ROOT_DEV == Root_NFS) { if (mount_nfs_root()) return; printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n"); ROOT_DEV = Root_FD0; } #endif #ifdef CONFIG_BLK_DEV_FD if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) { /* rd_doload is 2 for a dual initrd/ramload setup */ if (rd_doload==2) { if (rd_load_disk(1)) { ROOT_DEV = Root_RAM1; root_device_name = NULL; } } else change_floppy("root floppy"); } #endif #ifdef CONFIG_BLOCK create_dev("/dev/root", ROOT_DEV); mount_block_root("/dev/root", root_mountflags); #endif } /* * Prepare the namespace - decide what/where to mount, load ramdisks, etc. */ void __init prepare_namespace(void) { int is_floppy; if (root_delay) { printk(KERN_INFO "Waiting %dsec before mounting root device...\n", root_delay); ssleep(root_delay); } /* * wait for the known devices to complete their probing * * Note: this is a potential source of long boot delays. * For example, it is not atypical to wait 5 seconds here * for the touchpad of a laptop to initialize. */ wait_for_device_probe(); md_run_setup(); if (saved_root_name[0]) { root_device_name = saved_root_name; if (!strncmp(root_device_name, "mtd", 3) || !strncmp(root_device_name, "ubi", 3)) { mount_block_root(root_device_name, root_mountflags); goto out; } ROOT_DEV = name_to_dev_t(root_device_name); if (strncmp(root_device_name, "/dev/", 5) == 0) root_device_name += 5; } if (initrd_load()) goto out; /* wait for any asynchronous scanning to complete */ if ((ROOT_DEV == 0) && root_wait) { printk(KERN_INFO "Waiting for root device %s...\n", saved_root_name); while (driver_probe_done() != 0 || (ROOT_DEV = name_to_dev_t(saved_root_name)) == 0) msleep(100); async_synchronize_full(); } is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; if (is_floppy && rd_doload && rd_load_disk(0)) ROOT_DEV = Root_RAM0; mount_root(); out: devtmpfs_mount("dev"); sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot("."); }
/** * software_resume - Resume from a saved hibernation image. * * This routine is called as a late initcall, when all devices have been * discovered and initialized already. * * The image reading code is called to see if there is a hibernation image * available for reading. If that is the case, devices are quiesced and the * contents of memory is restored from the saved image. * * If this is successful, control reappears in the restored target kernel in * hibernation_snaphot() which returns to hibernate(). Otherwise, the routine * attempts to recover gracefully and make the kernel return to the normal mode * of operation. */ int software_resume(void) { int error; unsigned int flags; resume_attempted = 1; /* * We can't know (until an image header - if any - is loaded), whether * we did override swsusp. We therefore ensure that both are tried. */ try_tuxonice_resume(); /* * If the user said "noresume".. bail out early. */ if (noresume) return 0; /* * name_to_dev_t() below takes a sysfs buffer mutex when sysfs * is configured into the kernel. Since the regular hibernate * trigger path is via sysfs which takes a buffer mutex before * calling hibernate functions (which take pm_mutex) this can * cause lockdep to complain about a possible ABBA deadlock * which cannot happen since we're in the boot code here and * sysfs can't be invoked yet. Therefore, we use a subclass * here to avoid lockdep complaining. */ mutex_lock_nested(&pm_mutex, SINGLE_DEPTH_NESTING); if (swsusp_resume_device) goto Check_image; if (!strlen(resume_file)) { error = -ENOENT; goto Unlock; } pr_debug("PM: Checking hibernation image partition %s\n", resume_file); if (resume_delay) { printk(KERN_INFO "Waiting %dsec before reading resume device...\n", resume_delay); ssleep(resume_delay); } /* Check if the device is there */ swsusp_resume_device = name_to_dev_t(resume_file); /* * name_to_dev_t is ineffective to verify parition if resume_file is in * integer format. (e.g. major:minor) */ if (isdigit(resume_file[0]) && resume_wait) { int partno; while (!get_gendisk(swsusp_resume_device, &partno)) msleep(10); } if (!swsusp_resume_device) { /* * Some device discovery might still be in progress; we need * to wait for this to finish. */ wait_for_device_probe(); if (resume_wait) { while ((swsusp_resume_device = name_to_dev_t(resume_file)) == 0) msleep(10); async_synchronize_full(); } /* * We can't depend on SCSI devices being available after loading * one of their modules until scsi_complete_async_scans() is * called and the resume device usually is a SCSI one. */ scsi_complete_async_scans(); swsusp_resume_device = name_to_dev_t(resume_file); if (!swsusp_resume_device) { error = -ENODEV; goto Unlock; } } Check_image: pr_debug("PM: Hibernation image partition %d:%d present\n", MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device)); pr_debug("PM: Looking for hibernation image.\n"); error = swsusp_check(); if (error) goto Unlock; /* The snapshot device should not be opened while we're running */ if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { error = -EBUSY; swsusp_close(FMODE_READ); goto Unlock; } pm_prepare_console(); error = pm_notifier_call_chain(PM_RESTORE_PREPARE); if (error) goto close_finish; error = create_basic_memory_bitmaps(); if (error) goto close_finish; pr_debug("PM: Preparing processes for restore.\n"); error = freeze_processes(); if (error) { swsusp_close(FMODE_READ); goto Done; } pr_debug("PM: Loading hibernation image.\n"); error = swsusp_read(&flags); swsusp_close(FMODE_READ); if (!error) hibernation_restore(flags & SF_PLATFORM_MODE); printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n"); swsusp_free(); thaw_processes(); Done: free_basic_memory_bitmaps(); Finish: pm_notifier_call_chain(PM_POST_RESTORE); pm_restore_console(); atomic_inc(&snapshot_device_available); /* For success case, the suspend path will release the lock */ Unlock: mutex_unlock(&pm_mutex); pr_debug("PM: Hibernation image not present or could not be loaded.\n"); return error; close_finish: swsusp_close(FMODE_READ); goto Finish; }
static void md_setup_drive(void) { int dev_minor, i, ent, partitioned; dev_t dev; dev_t devices[MD_SB_DISKS + 1]; for (ent = 0; ent < md_setup_ents; ent++) { int fd; int err = 0; char *devname; mdu_disk_info_t dinfo; char name[16]; struct stat st_chk; dev_minor = md_setup_args[ent].minor; partitioned = md_setup_args[ent].partitioned; devname = md_setup_args[ent].device_names; snprintf(name, sizeof name, "/dev/md%s%d", partitioned ? "_d" : "", dev_minor); if (stat(name, &st_chk) == 0) continue; if (partitioned) dev = makedev(mdp_major(), dev_minor << MdpMinorShift); else dev = makedev(MD_MAJOR, dev_minor); create_dev(name, dev); for (i = 0; i < MD_SB_DISKS && devname != 0; i++) { char *p; p = strchr(devname, ','); if (p) *p++ = 0; dev = name_to_dev_t(devname); if (!dev) { fprintf(stderr, "md: Unknown device name: %s\n", devname); break; } devices[i] = dev; devname = p; } devices[i] = 0; if (!i) continue; fprintf(stderr, "md: Loading md%s%d: %s\n", partitioned ? "_d" : "", dev_minor, md_setup_args[ent].device_names); fd = open(name, 0, 0); if (fd < 0) { fprintf(stderr, "md: open failed - cannot start " "array %s\n", name); continue; } if (ioctl(fd, SET_ARRAY_INFO, 0) == -EBUSY) { fprintf(stderr, "md: Ignoring md=%d, already autodetected. (Use raid=noautodetect)\n", dev_minor); close(fd); continue; } if (md_setup_args[ent].level != LEVEL_NONE) { /* non-persistent */ mdu_array_info_t ainfo; ainfo.level = md_setup_args[ent].level; ainfo.size = 0; ainfo.nr_disks = 0; ainfo.raid_disks = 0; while (devices[ainfo.raid_disks]) ainfo.raid_disks++; ainfo.md_minor = dev_minor; ainfo.not_persistent = 1; ainfo.state = (1 << MD_SB_CLEAN); ainfo.layout = 0; ainfo.chunk_size = md_setup_args[ent].chunk; err = ioctl(fd, SET_ARRAY_INFO, &ainfo); for (i = 0; !err && i <= MD_SB_DISKS; i++) { dev = devices[i]; if (!dev) break; dinfo.number = i; dinfo.raid_disk = i; dinfo.state = (1 << MD_DISK_ACTIVE) | (1 << MD_DISK_SYNC); dinfo.major = major(dev); dinfo.minor = minor(dev); err = ioctl(fd, ADD_NEW_DISK, &dinfo); } } else { /* persistent */ for (i = 0; i <= MD_SB_DISKS; i++) { dev = devices[i]; if (!dev) break; dinfo.major = major(dev); dinfo.minor = minor(dev); ioctl(fd, ADD_NEW_DISK, &dinfo); } } if (!err) err = ioctl(fd, RUN_ARRAY, 0); if (err) fprintf(stderr, "md: starting md%d failed\n", dev_minor); else { /* reread the partition table. * I (neilb) and not sure why this is needed, but I * cannot boot a kernel with devfs compiled in from * partitioned md array without it */ close(fd); fd = open(name, 0, 0); ioctl(fd, BLKRRPART, 0); } close(fd); } }
static int software_resume(void) { int error; unsigned int flags; /* * If the user said "noresume".. bail out early. */ if (noresume) return 0; /* * name_to_dev_t() below takes a sysfs buffer mutex when sysfs * is configured into the kernel. Since the regular hibernate * trigger path is via sysfs which takes a buffer mutex before * calling hibernate functions (which take pm_mutex) this can * cause lockdep to complain about a possible ABBA deadlock * which cannot happen since we're in the boot code here and * sysfs can't be invoked yet. Therefore, we use a subclass * here to avoid lockdep complaining. */ mutex_lock_nested(&pm_mutex, SINGLE_DEPTH_NESTING); if (swsusp_resume_device) goto Check_image; if (!strlen(resume_file)) { error = -ENOENT; goto Unlock; } pr_debug("PM: Checking image partition %s\n", resume_file); /* Check if the device is there */ swsusp_resume_device = name_to_dev_t(resume_file); if (!swsusp_resume_device) { /* * Some device discovery might still be in progress; we need * to wait for this to finish. */ wait_for_device_probe(); /* * We can't depend on SCSI devices being available after loading * one of their modules until scsi_complete_async_scans() is * called and the resume device usually is a SCSI one. */ scsi_complete_async_scans(); swsusp_resume_device = name_to_dev_t(resume_file); if (!swsusp_resume_device) { error = -ENODEV; goto Unlock; } } Check_image: pr_debug("PM: Resume from partition %d:%d\n", MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device)); pr_debug("PM: Checking hibernation image.\n"); error = swsusp_check(); if (error) goto Unlock; /* The snapshot device should not be opened while we're running */ if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { error = -EBUSY; swsusp_close(FMODE_READ); goto Unlock; } pm_prepare_console(); error = pm_notifier_call_chain(PM_RESTORE_PREPARE); if (error) goto close_finish; error = usermodehelper_disable(); if (error) goto close_finish; error = create_basic_memory_bitmaps(); if (error) goto close_finish; pr_debug("PM: Preparing processes for restore.\n"); error = prepare_processes(); if (error) { swsusp_close(FMODE_READ); goto Done; } pr_debug("PM: Reading hibernation image.\n"); error = swsusp_read(&flags); swsusp_close(FMODE_READ); if (!error) hibernation_restore(flags & SF_PLATFORM_MODE); printk(KERN_ERR "PM: Restore failed, recovering.\n"); swsusp_free(); thaw_processes(); Done: free_basic_memory_bitmaps(); usermodehelper_enable(); Finish: pm_notifier_call_chain(PM_POST_RESTORE); pm_restore_console(); atomic_inc(&snapshot_device_available); /* For success case, the suspend path will release the lock */ Unlock: mutex_unlock(&pm_mutex); pr_debug("PM: Resume from disk failed.\n"); return error; close_finish: swsusp_close(FMODE_READ); goto Finish; }
int main(int argc, char *argv[]) { char **cmdv, **args; char *cmdlines[3]; int i; const char *errmsg; int ret = 0; int cmdc; int fd; struct timeval now; char *mount_argv[] = {"mount_part", "rootfs", "/root"}; pid_t pid; int nandboot = 0; gettimeofday(&now, NULL); srand48(now.tv_usec ^ (now.tv_sec << 24)); /* Default parameters for anything init-like we execute */ init_argc = argc; init_argv = alloca((argc+1)*sizeof(char *)); memcpy(init_argv, argv, (argc+1)*sizeof(char *)); /* * omit /dev/console when generating initramfs, * so we create it dynamically */ if (access("/dev/console", O_RDWR)) { mknod("/dev/console", S_IFCHR|0644, makedev(5, 1)); } if ((fd = open("/dev/console", O_RDWR)) != -1) { dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); if (fd > STDERR_FILENO) { close(fd); } } mnt_procfs = mount_sys_fs("/proc/cmdline", "/proc", "proc") >= 0; if (!mnt_procfs) { ret = 1; goto bail; } mnt_sysfs = mount_sys_fs("/sys/bus", "/sys", "sysfs") >= 0; if (!mnt_sysfs) { ret = 1; goto bail; } /* Construct the effective kernel command line. The effective kernel command line consists of /arch.cmd, if it exists, /proc/cmdline, plus any arguments after an -- argument on the proper command line, in that order. */ ret = readfile("/arch.cmd", &cmdlines[0]); if (ret < 0) cmdlines[0] = ""; ret = readfile("/proc/cmdline", &cmdlines[1]); if (ret < 0) { fprintf(stderr, "%s: cannot read /proc/cmdline\n", progname); ret = 1; goto bail; } cmdlines[2] = NULL; /* Find an -- argument, and if so append to the command line */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "--")) { i++; break; } } args = &argv[i]; /* Points either to first argument past -- or to the final NULL */ /* Count the number of arguments */ cmdc = split_cmdline(INT_MAX, NULL, argv[0], cmdlines, args); /* Actually generate the cmdline array */ cmdv = (char **)alloca((cmdc+1)*sizeof(char *)); if (split_cmdline(cmdc, cmdv, argv[0], cmdlines, args) != cmdc) { ret = 1; goto bail; } /* Debugging... */ dump_args(cmdc, cmdv); { const char * root_device_name = get_arg(cmdc, cmdv, "root="); if (strncmp(root_device_name, "/dev/mtdblock", strlen("/dev/mtdblock")) == 0) { nandboot = 1; printf("kinit: NAND mode, check online upgrade flag\n"); do_rootfs_OU(); } else { nandboot = 0; printf("kinit: None-NAND mode, ignore online upgrade flag\n"); } } /* Resume from suspend-to-disk, if appropriate */ /* If successful, does not return */ do_resume(cmdc, cmdv); /* Initialize networking, if applicable */ do_ipconfig(cmdc, cmdv); check_path("/root"); if (nandboot) { int index = 0; while (1) { char name[128]; snprintf(name, sizeof(name), "/sys/block/mtdblock%d", index); if (access(name, F_OK) == 0) { snprintf(name, sizeof(name), "/dev/mtdblock%d", index); create_dev(name, name_to_dev_t(name)); index++; } else { break; } } if((pid=fork())<0) fprintf(stderr, "fork error.\n"); else if(pid == 0) { if((ret = execve("/bin/mount_part", mount_argv, NULL)) <0) perror("excute mount_part error\n"); } if(waitpid(pid, NULL, 0) < 0) fprintf(stderr, "wait mount_part error.\n"); } else { do_mounts(cmdc, cmdv); } if (mnt_procfs) { umount2("/proc", 0); mnt_procfs = 0; } if (mnt_sysfs) { umount2("/sys", 0); mnt_sysfs = 0; } make_devices(); init_path = find_init("/root", get_arg(cmdc, cmdv, "init=")); if (!init_path) { fprintf(stderr, "%s: init not found!\n", progname); ret = 2; goto bail; } DEBUG(("kinit: init_path = %s, init=%s\n", init_path, get_arg(cmdc, cmdv, "init="))); init_argv[0] = strrchr(init_path, '/') + 1; errmsg = run_init("/root", "/dev/console", init_path, init_argv); /* If run_init returned, something went bad */ fprintf(stderr, "%s: %s: %s\n", progname, errmsg, strerror(errno)); ret = 2; goto bail; bail: if (mnt_procfs) umount2("/proc", 0); if (mnt_sysfs) umount2("/sys", 0); /* * If we get here, something bad probably happened, and the kernel * will most likely panic. Drain console output so the user can * figure out what happened. */ tcdrain(2); tcdrain(1); return ret; }
static int software_resume(void) { int error; unsigned int flags; /* * name_to_dev_t() below takes a sysfs buffer mutex when sysfs * is configured into the kernel. Since the regular hibernate * trigger path is via sysfs which takes a buffer mutex before * calling hibernate functions (which take pm_mutex) this can * cause lockdep to complain about a possible ABBA deadlock * which cannot happen since we're in the boot code here and * sysfs can't be invoked yet. Therefore, we use a subclass * here to avoid lockdep complaining. */ mutex_lock_nested(&pm_mutex, SINGLE_DEPTH_NESTING); if (!swsusp_resume_device) { if (!strlen(resume_file)) { mutex_unlock(&pm_mutex); return -ENOENT; } swsusp_resume_device = name_to_dev_t(resume_file); pr_debug("PM: Resume from partition %s\n", resume_file); } else { pr_debug("PM: Resume from partition %d:%d\n", MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device)); } if (noresume) { /** * FIXME: If noresume is specified, we need to find the * partition and reset it back to normal swap space. */ mutex_unlock(&pm_mutex); return 0; } pr_debug("PM: Checking hibernation image.\n"); error = swsusp_check(); if (error) goto Unlock; /* The snapshot device should not be opened while we're running */ if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { error = -EBUSY; goto Unlock; } pm_prepare_console(); error = pm_notifier_call_chain(PM_RESTORE_PREPARE); if (error) goto Finish; error = create_basic_memory_bitmaps(); if (error) goto Finish; pr_debug("PM: Preparing processes for restore.\n"); error = prepare_processes(); if (error) { swsusp_close(); goto Done; } pr_debug("PM: Reading hibernation image.\n"); error = swsusp_read(&flags); if (!error) hibernation_restore(flags & SF_PLATFORM_MODE); printk(KERN_ERR "PM: Restore failed, recovering.\n"); swsusp_free(); thaw_processes(); Done: free_basic_memory_bitmaps(); Finish: pm_notifier_call_chain(PM_POST_RESTORE); pm_restore_console(); atomic_inc(&snapshot_device_available); /* For success case, the suspend path will release the lock */ Unlock: mutex_unlock(&pm_mutex); pr_debug("PM: Resume from disk failed.\n"); return error; }
static int software_resume(void) { int error; down(&pm_sem); if (!swsusp_resume_device) { if (!strlen(resume_file)) { up(&pm_sem); return -ENOENT; } swsusp_resume_device = name_to_dev_t(resume_file); pr_debug("swsusp: Resume From Partition %s\n", resume_file); } else { pr_debug("swsusp: Resume From Partition %d:%d\n", MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device)); } if (noresume) { /** * FIXME: If noresume is specified, we need to find the partition * and reset it back to normal swap space. */ up(&pm_sem); return 0; } pr_debug("PM: Checking swsusp image.\n"); if ((error = swsusp_check())) goto Done; pr_debug("PM: Preparing processes for restore.\n"); if ((error = prepare_processes())) { swsusp_close(); goto Done; } pr_debug("PM: Reading swsusp image.\n"); if ((error = swsusp_read())) goto Cleanup; pr_debug("PM: Preparing devices for restore.\n"); if ((error = device_suspend(PMSG_FREEZE))) { printk("Some devices failed to suspend\n"); goto Free; } mb(); pr_debug("PM: Restoring saved image.\n"); swsusp_resume(); pr_debug("PM: Restore failed, recovering.n"); device_resume(); Free: swsusp_free(); Cleanup: unprepare_processes(); Done: /* For success case, the suspend path will release the lock */ up(&pm_sem); pr_debug("PM: Resume from disk failed.\n"); return 0; }
static int software_resume(void) { int error; mutex_lock(&pm_mutex); if (!swsusp_resume_device) { if (!strlen(resume_file)) { mutex_unlock(&pm_mutex); return -ENOENT; } swsusp_resume_device = name_to_dev_t(resume_file); pr_debug("swsusp: Resume From Partition %s\n", resume_file); } else { pr_debug("swsusp: Resume From Partition %d:%d\n", MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device)); } if (noresume) { /** * FIXME: If noresume is specified, we need to find the partition * and reset it back to normal swap space. */ mutex_unlock(&pm_mutex); return 0; } pr_debug("PM: Checking swsusp image.\n"); error = swsusp_check(); if (error) goto Unlock; error = create_basic_memory_bitmaps(); if (error) goto Unlock; pr_debug("PM: Preparing processes for restore.\n"); error = prepare_processes(); if (error) { swsusp_close(); goto Done; } pr_debug("PM: Reading swsusp image.\n"); error = swsusp_read(); if (error) { swsusp_free(); goto Thaw; } pr_debug("PM: Preparing devices for restore.\n"); suspend_console(); error = device_suspend(PMSG_PRETHAW); if (error) goto Free; error = disable_nonboot_cpus(); if (!error) swsusp_resume(); enable_nonboot_cpus(); Free: swsusp_free(); device_resume(); resume_console(); Thaw: printk(KERN_ERR "PM: Restore failed, recovering.\n"); unprepare_processes(); Done: free_basic_memory_bitmaps(); /* For success case, the suspend path will release the lock */ Unlock: mutex_unlock(&pm_mutex); pr_debug("PM: Resume from disk failed.\n"); return 0; }
static void __init handle_initrd(void) { int error; int pid; real_root_dev = new_encode_dev(ROOT_DEV); create_dev("/dev/root.old", Root_RAM0); /* mount initrd on rootfs' /root */ mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); sys_mkdir("/old", 0700); root_fd = sys_open("/", 0, 0); old_fd = sys_open("/old", 0, 0); /* move initrd over / and chdir/chroot in initrd root */ sys_chdir("/root"); sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot("."); /* * In case that a resume from disk is carried out by linuxrc or one of * its children, we need to tell the freezer not to wait for us. */ current->flags |= PF_FREEZER_SKIP; pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); if (pid > 0) while (pid != sys_wait4(-1, NULL, 0, NULL)) yield(); #ifdef MY_DEF_HERE if (0 == strncmp(root_device_name, SYNO_MD, strlen(SYNO_MD))) { ROOT_DEV = name_to_dev_t(SYNO_DEV_MD); real_root_dev = new_encode_dev(ROOT_DEV); } #endif current->flags &= ~PF_FREEZER_SKIP; /* move initrd to rootfs' /old */ sys_fchdir(old_fd); sys_mount("/", ".", NULL, MS_MOVE, NULL); /* switch root and cwd back to / of rootfs */ sys_fchdir(root_fd); sys_chroot("."); sys_close(old_fd); sys_close(root_fd); if (new_decode_dev(real_root_dev) == Root_RAM0) { sys_chdir("/old"); return; } ROOT_DEV = new_decode_dev(real_root_dev); mount_root(); printk(KERN_NOTICE "Trying to move old root to /initrd ... "); error = sys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL); if (!error) printk("okay\n"); else { int fd = sys_open("/dev/root.old", O_RDWR, 0); if (error == -ENOENT) printk("/initrd does not exist. Ignored.\n"); else printk("failed\n"); printk(KERN_NOTICE "Unmounting old root\n"); sys_umount("/old", MNT_DETACH); printk(KERN_NOTICE "Trying to free ramdisk memory ... "); if (fd < 0) { error = fd; } else { error = sys_ioctl(fd, BLKFLSBUF, 0); sys_close(fd); } printk(!error ? "okay\n" : "failed\n"); } }
/** * software_resume - Resume from a saved hibernation image. * * This routine is called as a late initcall, when all devices have been * discovered and initialized already. * * The image reading code is called to see if there is a hibernation image * available for reading. If that is the case, devices are quiesced and the * contents of memory is restored from the saved image. * * If this is successful, control reappears in the restored target kernel in * hibernation_snapshot() which returns to hibernate(). Otherwise, the routine * attempts to recover gracefully and make the kernel return to the normal mode * of operation. */ static int software_resume(void) { int error, nr_calls = 0; /* * If the user said "noresume".. bail out early. */ if (noresume || !hibernation_available()) return 0; /* * name_to_dev_t() below takes a sysfs buffer mutex when sysfs * is configured into the kernel. Since the regular hibernate * trigger path is via sysfs which takes a buffer mutex before * calling hibernate functions (which take pm_mutex) this can * cause lockdep to complain about a possible ABBA deadlock * which cannot happen since we're in the boot code here and * sysfs can't be invoked yet. Therefore, we use a subclass * here to avoid lockdep complaining. */ mutex_lock_nested(&pm_mutex, SINGLE_DEPTH_NESTING); if (swsusp_resume_device) goto Check_image; if (!strlen(resume_file)) { error = -ENOENT; goto Unlock; } pr_debug("Checking hibernation image partition %s\n", resume_file); if (resume_delay) { pr_info("Waiting %dsec before reading resume device ...\n", resume_delay); ssleep(resume_delay); } /* Check if the device is there */ swsusp_resume_device = name_to_dev_t(resume_file); /* * name_to_dev_t is ineffective to verify parition if resume_file is in * integer format. (e.g. major:minor) */ if (isdigit(resume_file[0]) && resume_wait) { int partno; while (!get_gendisk(swsusp_resume_device, &partno)) msleep(10); } if (!swsusp_resume_device) { /* * Some device discovery might still be in progress; we need * to wait for this to finish. */ wait_for_device_probe(); if (resume_wait) { while ((swsusp_resume_device = name_to_dev_t(resume_file)) == 0) msleep(10); async_synchronize_full(); } swsusp_resume_device = name_to_dev_t(resume_file); if (!swsusp_resume_device) { error = -ENODEV; goto Unlock; } } Check_image: pr_debug("Hibernation image partition %d:%d present\n", MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device)); pr_debug("Looking for hibernation image.\n"); error = swsusp_check(); if (error) goto Unlock; /* The snapshot device should not be opened while we're running */ if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { error = -EBUSY; swsusp_close(FMODE_READ); goto Unlock; } pm_prepare_console(); error = __pm_notifier_call_chain(PM_RESTORE_PREPARE, -1, &nr_calls); if (error) { nr_calls--; goto Close_Finish; } pr_debug("Preparing processes for restore.\n"); error = freeze_processes(); if (error) goto Close_Finish; error = load_image_and_restore(); thaw_processes(); Finish: __pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL); pm_restore_console(); atomic_inc(&snapshot_device_available); /* For success case, the suspend path will release the lock */ Unlock: mutex_unlock(&pm_mutex); pr_debug("Hibernation image not present or could not be loaded.\n"); return error; Close_Finish: swsusp_close(FMODE_READ); goto Finish; }
/* * Prepare the namespace - decide what/where to mount, load ramdisks, etc. */ void __init prepare_namespace(void) { int is_floppy; if (root_delay) { printk(KERN_INFO "Waiting %dsec before mounting root device...\n", root_delay); ssleep(root_delay); } /* * wait for the known devices to complete their probing * * Note: this is a potential source of long boot delays. * For example, it is not atypical to wait 5 seconds here * for the touchpad of a laptop to initialize. */ wait_for_device_probe(); md_run_setup(); if (saved_root_name[0]) { root_device_name = saved_root_name; if (!strncmp(root_device_name, "mtd", 3) || !strncmp(root_device_name, "ubi", 3)) { mount_block_root(root_device_name, root_mountflags); goto out; } #ifdef CONFIG_RTL_FLASH_DUAL_IMAGE_ENABLE extern int is_bank2_root(); //extern from rtl_gpio.c if(is_bank2_root()) //assume bank1 root is mtdblock1 , bank2's root is mtdblock3 strcpy(root_device_name,"/dev/mtdblock3"); #endif ROOT_DEV = name_to_dev_t(root_device_name); if (strncmp(root_device_name, "/dev/", 5) == 0) root_device_name += 5; } if (initrd_load()) goto out; /* wait for any asynchronous scanning to complete */ if ((ROOT_DEV == 0) && root_wait) { printk(KERN_INFO "Waiting for root device %s...\n", saved_root_name); while (driver_probe_done() != 0 || (ROOT_DEV = name_to_dev_t(saved_root_name)) == 0) msleep(100); async_synchronize_full(); } is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; if (is_floppy && rd_doload && rd_load_disk(0)) ROOT_DEV = Root_RAM0; mount_root(); out: sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot("."); }