summaryrefslogtreecommitdiffstats
path: root/common/blspec.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/blspec.c')
-rw-r--r--common/blspec.c219
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;