diff --git a/common/blspec.c b/common/blspec.c index 11e2a8a53..c3f0a3138 100644 --- a/common/blspec.c +++ b/common/blspec.c @@ -622,6 +622,41 @@ int blspec_scan_devicename(struct blspec *blspec, const char *devname) return blspec_scan_device(blspec, dev); } +static int blspec_append_root(struct blspec_entry *entry) +{ + const char *appendroot; + const char *rootarg; + struct device_d *fsdev; + int ret; + + appendroot = blspec_entry_var_get(entry, "appendroot"); + if (!appendroot || strcmp(appendroot, "true")) + return 0; + + fsdev = get_dev_by_mountpath(entry->rootpath); + if (!fsdev) { + ret = -EINVAL; + pr_err("Cannot get fs device for %s\n", entry->rootpath); + goto err_out; + } + + rootarg = dev_get_param(fsdev, "linux.bootargs"); + if (!rootarg) { + ret = -EINVAL; + pr_err("rootarg not implemented for fs %s\n", dev_name(fsdev)); + goto err_out; + } + + globalvar_add_simple("linux.bootargs.dyn.blspec.appendroot", rootarg); + + return 0; + +err_out: + pr_err("unable to append root argument\n"); + + return ret; +} + /* * blspec_boot - boot an entry * @@ -671,6 +706,10 @@ int blspec_boot(struct blspec_entry *entry, int verbose, int dryrun) globalvar_add_simple("linux.bootargs.dyn.blspec", options); + ret = blspec_append_root(entry); + if (ret) + goto err_out; + pr_info("booting %s from %s\n", blspec_entry_var_get(entry, "title"), entry->cdev ? dev_name(entry->cdev->dev) : "none"); @@ -689,7 +728,7 @@ int blspec_boot(struct blspec_entry *entry, int verbose, int dryrun) ret = bootm_boot(&data); if (ret) pr_err("Booting failed\n"); - +err_out: free((char *)data.oftree_file); free((char *)data.initrd_file); free((char *)data.os_file); diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index 08cb8dd7e..7fc1aa8d7 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c @@ -36,6 +36,7 @@ void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di) di->min_io_size = ubi->min_io_size; di->max_write_size = ubi->max_write_size; di->ro_mode = ubi->ro_mode; + di->mtd = ubi->mtd; } EXPORT_SYMBOL_GPL(ubi_do_get_device_info); diff --git a/fs/fs.c b/fs/fs.c index 779f2641b..981f653a7 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -225,6 +225,19 @@ struct cdev *get_cdev_by_mountpath(const char *path) return fsdev->cdev; } +/* + * get_cdev_by_mountpath - return the cdev the given path + * is mounted on + */ +struct device_d *get_dev_by_mountpath(const char *path) +{ + struct fs_device_d *fsdev; + + fsdev = get_fsdevice_by_path(path); + + return &fsdev->dev; +} + char *get_mounted_path(const char *path) { struct fs_device_d *fdev; diff --git a/fs/nfs.c b/fs/nfs.c index 2738c781d..ba00270a8 100644 --- a/fs/nfs.c +++ b/fs/nfs.c @@ -1306,6 +1306,20 @@ static int nfs_stat(struct device_d *dev, const char *filename, struct stat *s) } } +static void nfs_set_rootarg(struct nfs_priv *npriv, struct device_d *dev) +{ + char *str; + const char *ip; + + ip = ip_to_string(npriv->server); + str = asprintf("root=/dev/nfs nfsroot=%s:%s,v3,tcp", + ip, npriv->path); + + dev_add_param_fixed(dev, "linux.bootargs", str); + + free(str); +} + static int nfs_probe(struct device_d *dev) { struct fs_device_d *fsdev = dev_to_fs_device(dev); @@ -1369,6 +1383,8 @@ static int nfs_probe(struct device_d *dev) goto err2; } + nfs_set_rootarg(npriv, dev); + free(tmp); return 0; diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c index 68d90b36e..48a68372d 100644 --- a/fs/ubifs/ubifs.c +++ b/fs/ubifs/ubifs.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "ubifs.h" @@ -584,6 +585,26 @@ static int ubifs_readlink(struct device_d *dev, const char *pathname, char *buf, return 0; } +static void ubifs_set_rootarg(struct ubifs_priv *priv, struct device_d *dev) +{ + struct ubi_volume_info vi = {}; + struct ubi_device_info di = {}; + struct mtd_info *mtd; + char *str; + + ubi_get_volume_info(priv->ubi, &vi); + ubi_get_device_info(vi.ubi_num, &di); + + mtd = di.mtd; + + str = asprintf("root=ubi0:%s ubi.mtd=%s rootfstype=ubifs", + vi.name, mtd->cdev.partname); + + dev_add_param_fixed(dev, "linux.bootargs", str); + + free(str); +} + static int ubifs_probe(struct device_d *dev) { struct fs_device_d *fsdev = dev_to_fs_device(dev); @@ -612,6 +633,8 @@ static int ubifs_probe(struct device_d *dev) goto err; } + ubifs_set_rootarg(priv, dev); + return 0; err: ubi_close_volume(priv->ubi); diff --git a/include/fs.h b/include/fs.h index f95464de6..81a166c37 100644 --- a/include/fs.h +++ b/include/fs.h @@ -174,6 +174,7 @@ char *normalise_link(const char *pathname, const char* symlink); char *get_mounted_path(const char *path); struct cdev *get_cdev_by_mountpath(const char *path); +struct device_d *get_dev_by_mountpath(const char *path); /* Register a new filesystem driver */ int register_fs_driver(struct fs_driver_d *fsdrv); diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h index 274ec4ee4..0614681d7 100644 --- a/include/linux/mtd/ubi.h +++ b/include/linux/mtd/ubi.h @@ -154,6 +154,7 @@ struct ubi_device_info { int max_write_size; int ro_mode; dev_t cdev; + struct mtd_info *mtd; }; /*