Merge branch 'for-next/boot'
This commit is contained in:
commit
a5a82ca2cd
125
commands/boot.c
125
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)
|
static int bootscript_create_entry(struct blspec *blspec, const char *name)
|
||||||
{
|
{
|
||||||
struct blspec_entry *be;
|
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 = blspec_entry_alloc(blspec);
|
||||||
be->me.type = MENU_ENTRY_NORMAL;
|
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)
|
static void bootsources_menu(char *entries[], int num_entries)
|
||||||
{
|
{
|
||||||
struct blspec *blspec = NULL;
|
struct blspec *blspec = NULL;
|
||||||
struct blspec_entry *entry;
|
struct blspec_entry *entry, *entry_default;
|
||||||
struct menu_entry *back_entry;
|
struct menu_entry *back_entry;
|
||||||
|
|
||||||
if (!IS_ENABLED(CONFIG_MENU)) {
|
if (!IS_ENABLED(CONFIG_MENU)) {
|
||||||
|
@ -247,10 +252,16 @@ static void bootsources_menu(char *entries[], int num_entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
blspec = bootentries_collect(entries, num_entries);
|
blspec = bootentries_collect(entries, num_entries);
|
||||||
|
if (blspec)
|
||||||
|
return;
|
||||||
|
|
||||||
|
entry_default = blspec_entry_default(blspec);
|
||||||
|
|
||||||
blspec_for_each_entry(blspec, entry) {
|
blspec_for_each_entry(blspec, entry) {
|
||||||
entry->me.action = bootsource_action;
|
entry->me.action = bootsource_action;
|
||||||
menu_add_entry(blspec->menu, &entry->me);
|
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));
|
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)
|
static void bootsources_list(char *entries[], int num_entries)
|
||||||
{
|
{
|
||||||
struct blspec *blspec;
|
struct blspec *blspec;
|
||||||
struct blspec_entry *entry;
|
struct blspec_entry *entry, *entry_default;
|
||||||
|
|
||||||
blspec = bootentries_collect(entries, num_entries);
|
blspec = bootentries_collect(entries, num_entries);
|
||||||
|
if (!blspec)
|
||||||
|
return;
|
||||||
|
|
||||||
printf("%-20s %-20s %s\n", "device", "hwdevice", "title");
|
entry_default = blspec_entry_default(blspec);
|
||||||
printf("%-20s %-20s %s\n", "------", "--------", "-----");
|
|
||||||
|
printf(" %-20s %-20s %s\n", "device", "hwdevice", "title");
|
||||||
|
printf(" %-20s %-20s %s\n", "------", "--------", "-----");
|
||||||
|
|
||||||
blspec_for_each_entry(blspec, entry) {
|
blspec_for_each_entry(blspec, entry) {
|
||||||
|
if (entry == entry_default)
|
||||||
|
printf("* ");
|
||||||
|
else
|
||||||
|
printf(" ");
|
||||||
|
|
||||||
if (entry->scriptpath)
|
if (entry->scriptpath)
|
||||||
printf("%-40s %s\n", basename(entry->scriptpath), entry->me.display);
|
printf("%-40s %s\n", basename(entry->scriptpath), entry->me.display);
|
||||||
else
|
else
|
||||||
|
@ -307,7 +327,7 @@ static void bootsources_list(char *entries[], int num_entries)
|
||||||
static int boot(const char *name)
|
static int boot(const char *name)
|
||||||
{
|
{
|
||||||
struct blspec *blspec;
|
struct blspec *blspec;
|
||||||
struct blspec_entry *entry;
|
struct blspec_entry *entry, *entry_default;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
blspec = blspec_alloc();
|
blspec = blspec_alloc();
|
||||||
|
@ -320,7 +340,19 @@ static int boot(const char *name)
|
||||||
return -ENOENT;
|
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) {
|
blspec_for_each_entry(blspec, entry) {
|
||||||
|
if (entry == entry_default)
|
||||||
|
continue;
|
||||||
|
|
||||||
printf("booting %s\n", entry->me.display);
|
printf("booting %s\n", entry->me.display);
|
||||||
ret = boot_entry(entry);
|
ret = boot_entry(entry);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
@ -333,9 +365,11 @@ static int boot(const char *name)
|
||||||
|
|
||||||
static int do_boot(int argc, char *argv[])
|
static int do_boot(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
const char *sources = NULL;
|
char *freep = NULL;
|
||||||
char *source, *freep;
|
|
||||||
int opt, ret = 0, do_list = 0, do_menu = 0;
|
int opt, ret = 0, do_list = 0, do_menu = 0;
|
||||||
|
char **sources;
|
||||||
|
int num_sources;
|
||||||
|
int i;
|
||||||
|
|
||||||
verbose = 0;
|
verbose = 0;
|
||||||
dryrun = 0;
|
dryrun = 0;
|
||||||
|
@ -361,47 +395,62 @@ static int do_boot(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (optind < argc) {
|
||||||
|
num_sources = argc - optind;
|
||||||
|
sources = xmemdup(&argv[optind], sizeof(char *) * num_sources);
|
||||||
|
} else {
|
||||||
|
const char *def;
|
||||||
|
char *sep;
|
||||||
|
|
||||||
|
def = getenv("global.boot.default");
|
||||||
|
if (!def)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (do_list) {
|
if (do_list) {
|
||||||
bootsources_list(&argv[optind], argc - optind);
|
bootsources_list(sources, num_sources);
|
||||||
return 0;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_menu) {
|
if (do_menu) {
|
||||||
bootsources_menu(&argv[optind], argc - optind);
|
bootsources_menu(sources, num_sources);
|
||||||
return 0;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optind < argc) {
|
for (i = 0; i < num_sources; i++) {
|
||||||
while (optind < argc) {
|
ret = boot(sources[i]);
|
||||||
source = argv[optind];
|
|
||||||
optind++;
|
|
||||||
ret = boot(source);
|
|
||||||
if (!ret)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
sources = getenv("global.boot.default");
|
|
||||||
if (!sources)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
freep = source = xstrdup(sources);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
char *sep = strchr(source, ' ');
|
|
||||||
if (sep)
|
|
||||||
*sep = 0;
|
|
||||||
ret = boot(source);
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
break;
|
break;
|
||||||
|
goto out;
|
||||||
if (sep)
|
|
||||||
source = sep + 1;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
free(sources);
|
||||||
free(freep);
|
free(freep);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -234,6 +234,78 @@ out:
|
||||||
return ret ? ERR_PTR(ret) : mountpath;
|
return ret ? ERR_PTR(ret) : mountpath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* blspec_scan_directory - scan over a directory
|
||||||
*
|
*
|
||||||
|
@ -313,12 +385,17 @@ int blspec_scan_directory(struct blspec *blspec, const char *root)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
found++;
|
|
||||||
|
|
||||||
entry->rootpath = xstrdup(root);
|
entry->rootpath = xstrdup(root);
|
||||||
entry->configpath = configname;
|
entry->configpath = configname;
|
||||||
entry->cdev = get_cdev_by_mountpath(root);
|
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);
|
name = asprintf("%s/%s", dirname, d->d_name);
|
||||||
if (entry_default && !strcmp(name, entry_default))
|
if (entry_default && !strcmp(name, entry_default))
|
||||||
entry->boot_default = true;
|
entry->boot_default = true;
|
||||||
|
|
|
@ -35,7 +35,6 @@ int blspec_boot_devicename(const char *devname, int verbose, int dryrun);
|
||||||
|
|
||||||
int blspec_scan_devices(struct blspec *blspec);
|
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_devicename(struct blspec *blspec, const char *devname);
|
||||||
int blspec_scan_directory(struct blspec *blspec, const char *root);
|
int blspec_scan_directory(struct blspec *blspec, const char *root);
|
||||||
|
|
||||||
|
@ -91,4 +90,13 @@ static inline void blspec_free(struct blspec *blspec)
|
||||||
free(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__ */
|
#endif /* __LOADER_H__ */
|
||||||
|
|
Loading…
Reference in New Issue