diff options
Diffstat (limited to 'common/blspec.c')
-rw-r--r-- | common/blspec.c | 219 |
1 files changed, 100 insertions, 119 deletions
diff --git a/common/blspec.c b/common/blspec.c index 158fd1e9a2..23a24c63db 100644 --- a/common/blspec.c +++ b/common/blspec.c @@ -15,6 +15,7 @@ #include <libbb.h> #include <init.h> #include <bootm.h> +#include <glob.h> #include <net.h> #include <fs.h> #include <of.h> @@ -87,7 +88,7 @@ static int blspec_boot(struct bootentry *be, int verbose, int dryrun) bootm_data_init_defaults(&data); - data.verbose = verbose || data.verbose; + data.verbose = max(verbose, data.verbose); devicetree = blspec_entry_var_get(entry, "devicetree"); initrd = blspec_entry_var_get(entry, "initrd"); @@ -315,7 +316,7 @@ static int blspec_have_entry(struct bootentries *bootentries, const char *path) */ static const char *nfs_find_mountpath(const char *nfshostpath) { - struct fs_device_d *fsdev; + struct fs_device *fsdev; for_each_fs_device(fsdev) { if (fsdev->backingstore && !strcmp(fsdev->backingstore, nfshostpath)) @@ -340,10 +341,10 @@ static char *parse_nfs_url(const char *url) int ret; if (!IS_ENABLED(CONFIG_FS_NFS)) - return ERR_PTR(-ENOSYS); + return NULL; if (strncmp(url, "nfs://", 6)) - return ERR_PTR(-EINVAL); + return NULL; url += 6; @@ -412,7 +413,7 @@ out: if (ret) free(mountpath); - return ret ? ERR_PTR(ret) : mountpath; + return ret ? NULL : mountpath; } /* @@ -425,10 +426,10 @@ static bool entry_is_of_compatible(struct blspec_entry *entry) { const char *devicetree; const char *abspath; - size_t size; - void *fdt = NULL; int ret; - struct device_node *root = NULL, *barebox_root; + struct device_node *barebox_root; + size_t size; + void *fdt; const char *compat; char *filename; @@ -458,33 +459,22 @@ static bool entry_is_of_compatible(struct blspec_entry *entry) fdt = read_file(filename, &size); if (!fdt) { - pr_err("Cannot read: %s\n", filename); - ret = false; - goto out; - } - - root = of_unflatten_dtb(fdt, size); - if (IS_ERR(root)) { ret = false; - root = NULL; goto out; } - if (of_device_is_compatible(root, compat)) { + if (fdt_machine_is_compatible(fdt, size, compat)) { ret = true; goto out; } - pr_info("ignoring entry with incompatible devicetree \"%s\"\n", - (char *)of_get_property(root, "compatible", NULL)); + pr_info("ignoring entry with incompatible devicetree: %s\n", devicetree); ret = false; out: - if (root) - of_delete_node(root); - free(filename); free(fdt); + free(filename); return ret; } @@ -513,6 +503,55 @@ static bool entry_is_match_machine_id(struct blspec_entry *entry) return ret; } +int blspec_scan_file(struct bootentries *bootentries, const char *root, + const char *configname) +{ + char *devname = NULL, *hwdevname = NULL; + struct blspec_entry *entry; + + if (blspec_have_entry(bootentries, configname)) + return -EEXIST; + + entry = blspec_entry_open(bootentries, configname); + if (IS_ERR(entry)) + return PTR_ERR(entry); + + root = root ?: get_mounted_path(configname); + entry->rootpath = xstrdup(root); + entry->configpath = xstrdup(configname); + entry->cdev = get_cdev_by_mountpath(root); + + if (!entry_is_of_compatible(entry)) { + blspec_entry_free(&entry->entry); + return -ENODEV; + } + + if (!entry_is_match_machine_id(entry)) { + blspec_entry_free(&entry->entry); + return -ENODEV; + } + + if (entry->cdev && entry->cdev->dev) { + devname = xstrdup(dev_name(entry->cdev->dev)); + if (entry->cdev->dev->parent) + hwdevname = xstrdup(dev_name(entry->cdev->dev->parent)); + } + + entry->entry.title = xasprintf("%s (%s)", blspec_entry_var_get(entry, "title"), + configname); + entry->entry.description = basprintf("blspec entry, device: %s hwdevice: %s", + devname ? devname : "none", + hwdevname ? hwdevname : "none"); + free(devname); + free(hwdevname); + + entry->entry.me.type = MENU_ENTRY_NORMAL; + entry->entry.release = blspec_entry_free; + + bootentries_add_entry(bootentries, &entry->entry); + return 1; +} + /* * blspec_scan_directory - scan over a directory * @@ -522,115 +561,40 @@ static bool entry_is_match_machine_id(struct blspec_entry *entry) */ int blspec_scan_directory(struct bootentries *bootentries, const char *root) { - struct blspec_entry *entry; - DIR *dir; - struct dirent *d; + glob_t globb; char *abspath; int ret, found = 0; const char *dirname = "loader/entries"; - char *nfspath = NULL; - - nfspath = parse_nfs_url(root); - if (!IS_ERR(nfspath)) - root = nfspath; + int i; pr_debug("%s: %s %s\n", __func__, root, dirname); - abspath = basprintf("%s/%s", root, dirname); + abspath = basprintf("%s/%s/*.conf", root, dirname); - dir = opendir(abspath); - if (!dir) { + ret = glob(abspath, 0, NULL, &globb); + if (ret) { pr_debug("%s: %s: %s\n", __func__, abspath, strerror(errno)); ret = -errno; goto err_out; } - while ((d = readdir(dir))) { - char *configname; + for (i = 0; i < globb.gl_pathc; i++) { + const char *configname = globb.gl_pathv[i]; struct stat s; - char *dot; - char *devname = NULL, *hwdevname = NULL; - - if (*d->d_name == '.') - continue; - - configname = basprintf("%s/%s", abspath, d->d_name); - - dot = strrchr(configname, '.'); - if (!dot) { - free(configname); - continue; - } - - if (strcmp(dot, ".conf")) { - free(configname); - continue; - } ret = stat(configname, &s); - if (ret) { - free(configname); - continue; - } - - if (!S_ISREG(s.st_mode)) { - free(configname); + if (ret || !S_ISREG(s.st_mode)) continue; - } - - if (blspec_have_entry(bootentries, configname)) { - free(configname); - continue; - } - entry = blspec_entry_open(bootentries, configname); - if (IS_ERR(entry)) { - free(configname); - continue; - } - - entry->rootpath = xstrdup(root); - entry->configpath = configname; - entry->cdev = get_cdev_by_mountpath(root); - - if (!entry_is_of_compatible(entry)) { - blspec_entry_free(&entry->entry); - continue; - } - - if (!entry_is_match_machine_id(entry)) { - blspec_entry_free(&entry->entry); - continue; - } - - found++; - - if (entry->cdev && entry->cdev->dev) { - devname = xstrdup(dev_name(entry->cdev->dev)); - if (entry->cdev->dev->parent) - hwdevname = xstrdup(dev_name(entry->cdev->dev->parent)); - } - - entry->entry.title = xasprintf("%s (%s)", blspec_entry_var_get(entry, "title"), - configname); - entry->entry.description = basprintf("blspec entry, device: %s hwdevice: %s", - devname ? devname : "none", - hwdevname ? hwdevname : "none"); - free(devname); - free(hwdevname); - - entry->entry.me.type = MENU_ENTRY_NORMAL; - entry->entry.release = blspec_entry_free; - - bootentries_add_entry(bootentries, &entry->entry); + ret = blspec_scan_file(bootentries, root, configname); + if (ret > 0) + found += ret; } ret = found; - closedir(dir); + globfree(&globb); err_out: - if (!IS_ERR(nfspath)) - free(nfspath); free(abspath); return ret; @@ -647,7 +611,7 @@ err_out: */ static int blspec_scan_ubi(struct bootentries *bootentries, struct cdev *cdev) { - struct device_d *child; + struct device *child; int ret, found = 0; pr_debug("%s: %s\n", __func__, cdev->name); @@ -702,9 +666,7 @@ static int blspec_scan_cdev(struct bootentries *bootentries, struct cdev *cdev) found += ret; } - rootpath = cdev_get_mount_path(cdev); - if (!rootpath) - rootpath = cdev_mount_default(cdev, NULL); + rootpath = cdev_mount(cdev); if (!IS_ERR(rootpath)) { ret = blspec_scan_directory(bootentries, rootpath); if (ret > 0) @@ -723,7 +685,7 @@ static int blspec_scan_cdev(struct bootentries *bootentries, struct cdev *cdev) */ int blspec_scan_devices(struct bootentries *bootentries) { - struct device_d *dev; + struct device *dev; struct block_device *bdev; int ret, found = 0; @@ -751,9 +713,9 @@ int blspec_scan_devices(struct bootentries *bootentries) * Returns the number of entries found or a negative error code if some unexpected * error occurred. */ -int blspec_scan_device(struct bootentries *bootentries, struct device_d *dev) +int blspec_scan_device(struct bootentries *bootentries, struct device *dev) { - struct device_d *child; + struct device *child; struct cdev *cdev; int ret, found = 0; @@ -767,7 +729,7 @@ int blspec_scan_device(struct bootentries *bootentries, struct device_d *dev) * partition with the MBR type id of 0xEA already exists it * should be used as $BOOT */ - if (cdev->dos_partition_type == 0xea) { + if (cdev_is_mbr_partitioned(cdev->master) && cdev->dos_partition_type == 0xea) { ret = blspec_scan_cdev(bootentries, cdev); if (ret == 0) ret = -ENOENT; @@ -815,11 +777,14 @@ int blspec_scan_device(struct bootentries *bootentries, struct device_d *dev) */ int blspec_scan_devicename(struct bootentries *bootentries, const char *devname) { - struct device_d *dev; + struct device *dev; struct cdev *cdev; pr_debug("%s: %s\n", __func__, devname); + /* Support both boot /dev/disk0.rootfs and boot disk0.rootfs */ + devname += str_has_prefix(devname, "/dev/"); + device_detect_by_name(devname); cdev = cdev_by_name(devname); @@ -839,6 +804,7 @@ int blspec_scan_devicename(struct bootentries *bootentries, const char *devname) static int blspec_bootentry_provider(struct bootentries *bootentries, const char *name) { + struct stat s; int ret, found = 0; ret = blspec_scan_devicename(bootentries, name); @@ -846,9 +812,24 @@ static int blspec_bootentry_provider(struct bootentries *bootentries, found += ret; if (*name == '/' || !strncmp(name, "nfs://", 6)) { - ret = blspec_scan_directory(bootentries, name); + char *nfspath = parse_nfs_url(name); + + if (nfspath) + name = nfspath; + + ret = stat(name, &s); + if (ret) + goto out; + + if (S_ISDIR(s.st_mode)) + ret = blspec_scan_directory(bootentries, name); + else if (S_ISREG(s.st_mode) && strends(name, ".conf")) + ret = blspec_scan_file(bootentries, NULL, name); if (ret > 0) found += ret; + +out: + free(nfspath); } return found; |