summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2014-04-04 10:06:14 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2014-04-04 10:06:14 +0200
commita5a82ca2cd84d3a730025bed7414b35f041750b6 (patch)
tree94a5179267528e714dc6f2c0e8bc68343deab88f
parentb587c87aacbc9b6fe859cef97ca43dc353f8a44f (diff)
parent6979118edef2b57c3bb6f401b58a03ab6bb5a54e (diff)
downloadbarebox-a5a82ca2cd84d3a730025bed7414b35f041750b6.tar.gz
barebox-a5a82ca2cd84d3a730025bed7414b35f041750b6.tar.xz
Merge branch 'for-next/boot'
-rw-r--r--commands/boot.c121
-rw-r--r--common/blspec.c81
-rw-r--r--include/blspec.h10
3 files changed, 173 insertions, 39 deletions
diff --git a/commands/boot.c b/commands/boot.c
index bb8d07fce4..4a839790d1 100644
--- a/commands/boot.c
+++ b/commands/boot.c
@@ -106,6 +106,11 @@ static void bootsource_action(struct menu *m, struct menu_entry *me)
static int bootscript_create_entry(struct blspec *blspec, const char *name)
{
struct blspec_entry *be;
+ enum filetype type;
+
+ type = file_name_detect_type(name);
+ if (type != filetype_sh)
+ return -EINVAL;
be = blspec_entry_alloc(blspec);
be->me.type = MENU_ENTRY_NORMAL;
@@ -238,7 +243,7 @@ static struct blspec *bootentries_collect(char *entries[], int num_entries)
static void bootsources_menu(char *entries[], int num_entries)
{
struct blspec *blspec = NULL;
- struct blspec_entry *entry;
+ struct blspec_entry *entry, *entry_default;
struct menu_entry *back_entry;
if (!IS_ENABLED(CONFIG_MENU)) {
@@ -247,10 +252,16 @@ static void bootsources_menu(char *entries[], int num_entries)
}
blspec = bootentries_collect(entries, num_entries);
+ if (blspec)
+ return;
+
+ entry_default = blspec_entry_default(blspec);
blspec_for_each_entry(blspec, entry) {
entry->me.action = bootsource_action;
menu_add_entry(blspec->menu, &entry->me);
+ if (entry == entry_default)
+ menu_set_selected_entry(blspec->menu, &entry->me);
}
back_entry = xzalloc(sizeof(*back_entry));
@@ -275,14 +286,23 @@ static void bootsources_menu(char *entries[], int num_entries)
static void bootsources_list(char *entries[], int num_entries)
{
struct blspec *blspec;
- struct blspec_entry *entry;
+ struct blspec_entry *entry, *entry_default;
blspec = bootentries_collect(entries, num_entries);
+ if (!blspec)
+ return;
+
+ entry_default = blspec_entry_default(blspec);
- printf("%-20s %-20s %s\n", "device", "hwdevice", "title");
- printf("%-20s %-20s %s\n", "------", "--------", "-----");
+ printf(" %-20s %-20s %s\n", "device", "hwdevice", "title");
+ printf(" %-20s %-20s %s\n", "------", "--------", "-----");
blspec_for_each_entry(blspec, entry) {
+ if (entry == entry_default)
+ printf("* ");
+ else
+ printf(" ");
+
if (entry->scriptpath)
printf("%-40s %s\n", basename(entry->scriptpath), entry->me.display);
else
@@ -307,7 +327,7 @@ static void bootsources_list(char *entries[], int num_entries)
static int boot(const char *name)
{
struct blspec *blspec;
- struct blspec_entry *entry;
+ struct blspec_entry *entry, *entry_default;
int ret;
blspec = blspec_alloc();
@@ -320,7 +340,19 @@ static int boot(const char *name)
return -ENOENT;
}
+ entry_default = blspec_entry_default(blspec);
+ if (entry_default) {
+ ret = boot_entry(entry_default);
+ if (!ret)
+ return ret;
+ printf("booting %s failed: %s\n", entry_default->me.display,
+ strerror(-ret));
+ }
+
blspec_for_each_entry(blspec, entry) {
+ if (entry == entry_default)
+ continue;
+
printf("booting %s\n", entry->me.display);
ret = boot_entry(entry);
if (!ret)
@@ -333,9 +365,11 @@ static int boot(const char *name)
static int do_boot(int argc, char *argv[])
{
- const char *sources = NULL;
- char *source, *freep;
+ char *freep = NULL;
int opt, ret = 0, do_list = 0, do_menu = 0;
+ char **sources;
+ int num_sources;
+ int i;
verbose = 0;
dryrun = 0;
@@ -361,47 +395,62 @@ static int do_boot(int argc, char *argv[])
}
}
- if (do_list) {
- bootsources_list(&argv[optind], argc - optind);
- return 0;
- }
+ if (optind < argc) {
+ num_sources = argc - optind;
+ sources = xmemdup(&argv[optind], sizeof(char *) * num_sources);
+ } else {
+ const char *def;
+ char *sep;
- if (do_menu) {
- bootsources_menu(&argv[optind], argc - optind);
- return 0;
- }
+ def = getenv("global.boot.default");
+ if (!def)
+ return 0;
- if (optind < argc) {
- while (optind < argc) {
- source = argv[optind];
- optind++;
- ret = boot(source);
- if (!ret)
+ sep = freep = xstrdup(def);
+
+ num_sources = 0;
+
+ while (1) {
+ num_sources++;
+
+ sep = strchr(sep, ' ');
+ if (!sep)
break;
+ sep++;
+ }
+
+ sources = xmalloc(sizeof(char *) * num_sources);
+
+ sep = freep;
+
+ for (i = 0; i < num_sources; i++) {
+ sources[i] = sep;
+ sep = strchr(sep, ' ');
+ if (sep)
+ *sep = 0;
+ sep++;
}
- return ret;
}
- sources = getenv("global.boot.default");
- if (!sources)
- return 0;
+ if (do_list) {
+ bootsources_list(sources, num_sources);
+ goto out;
+ }
- freep = source = xstrdup(sources);
+ if (do_menu) {
+ bootsources_menu(sources, num_sources);
+ goto out;
+ }
- while (1) {
- char *sep = strchr(source, ' ');
- if (sep)
- *sep = 0;
- ret = boot(source);
+ for (i = 0; i < num_sources; i++) {
+ ret = boot(sources[i]);
if (!ret)
break;
-
- if (sep)
- source = sep + 1;
- else
- break;
+ goto out;
}
+out:
+ free(sources);
free(freep);
return ret;
diff --git a/common/blspec.c b/common/blspec.c
index 9b4b096a0a..f165b77aaa 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -235,6 +235,78 @@ out:
}
/*
+ * entry_is_of_compatible - check if a bootspec entry is compatible with
+ * the current machine.
+ *
+ * returns true is the entry is compatible, false otherwise
+ */
+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;
+ const char *compat;
+ char *filename;
+
+ /* If we don't have a root node every entry is compatible */
+ barebox_root = of_get_root_node();
+ if (!barebox_root)
+ return true;
+
+ ret = of_property_read_string(barebox_root, "compatible", &compat);
+ if (ret)
+ return false;
+
+ if (entry->rootpath)
+ abspath = entry->rootpath;
+ else
+ abspath = "";
+
+ /* If the entry doesn't specifiy a devicetree we are compatible */
+ devicetree = blspec_entry_var_get(entry, "devicetree");
+ if (!devicetree)
+ return true;
+
+ if (!strcmp(devicetree, "none"))
+ return true;
+
+ filename = asprintf("%s/%s", abspath, devicetree);
+
+ fdt = read_file(filename, &size);
+ if (!fdt) {
+ ret = false;
+ goto out;
+ }
+
+ root = of_unflatten_dtb(NULL, fdt);
+ if (IS_ERR(root)) {
+ ret = PTR_ERR(root);
+ goto out;
+ }
+
+ if (of_device_is_compatible(root, compat)) {
+ ret = true;
+ goto out;
+ }
+
+ pr_info("ignoring entry with incompatible devicetree \"%s\"\n",
+ (char *)of_get_property(root, "compatible", &size));
+
+ ret = false;
+
+out:
+ if (root)
+ of_delete_node(root);
+ free(filename);
+ free(fdt);
+
+ return ret;
+}
+
+/*
* blspec_scan_directory - scan over a directory
*
* Given a root path collects all blspec entries found under /blspec/entries/.
@@ -313,12 +385,17 @@ int blspec_scan_directory(struct blspec *blspec, const char *root)
continue;
}
- found++;
-
entry->rootpath = xstrdup(root);
entry->configpath = configname;
entry->cdev = get_cdev_by_mountpath(root);
+ if (!entry_is_of_compatible(entry)) {
+ blspec_entry_free(entry);
+ continue;
+ }
+
+ found++;
+
name = asprintf("%s/%s", dirname, d->d_name);
if (entry_default && !strcmp(name, entry_default))
entry->boot_default = true;
diff --git a/include/blspec.h b/include/blspec.h
index 66d2e8485d..afac5ed7ba 100644
--- a/include/blspec.h
+++ b/include/blspec.h
@@ -35,7 +35,6 @@ int blspec_boot_devicename(const char *devname, int verbose, int dryrun);
int blspec_scan_devices(struct blspec *blspec);
-struct blspec_entry *blspec_entry_default(struct blspec *l);
int blspec_scan_devicename(struct blspec *blspec, const char *devname);
int blspec_scan_directory(struct blspec *blspec, const char *root);
@@ -91,4 +90,13 @@ static inline void blspec_free(struct blspec *blspec)
free(blspec);
}
+#ifdef CONFIG_BLSPEC
+struct blspec_entry *blspec_entry_default(struct blspec *l);
+#else
+static inline struct blspec_entry *blspec_entry_default(struct blspec *l)
+{
+ return NULL;
+}
+#endif
+
#endif /* __LOADER_H__ */