Add initial dtb support
authorGeoff Levand <geoff@infradead.org>
Mon, 15 Apr 2013 22:23:05 +0000 (15:23 -0700)
committerJeremy Kerr <jk@ozlabs.org>
Mon, 24 Jun 2013 05:07:57 +0000 (13:07 +0800)
Updates & fixes by Jeremy Kerr <jk@ozlabs.org>.

Signed-off-by: Geoff Levand <geoff@infradead.org>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
12 files changed:
discover/boot.c
discover/device-handler.c
discover/device-handler.h
discover/kboot-parser.c
lib/pb-protocol/pb-protocol.c
lib/types/types.h
ui/common/discover-client.c
ui/common/discover-client.h
ui/ncurses/nc-boot-editor.c
ui/ncurses/nc-cui.c
ui/test/discover-test.c
ui/twin/pbt-client.c

index 5ca69b9f135f3cdbc032ccd7168311685e3adf5a..c922fb62c8de28587e9b893990c3bfec36914529 100644 (file)
  * kexec_load - kexec load helper.
  * @l_image: The local image file for kexec to execute.
  * @l_initrd: Optional local initrd file for kexec --initrd, can be NULL.
+ * @l_dtb: Optional local dtb file for kexec --dtb, can be NULL.
  * @args: Optional command line args for kexec --append, can be NULL.
  */
 
 static int kexec_load(const char *l_image, const char *l_initrd,
-       const char *args, int dry_run)
+       const char *l_dtb, const char *args, int dry_run)
 {
        int result;
-       const char *argv[6];
+       const char *argv[7];
        const char **p;
        char *s_initrd = NULL;
+       char *s_dtb = NULL;
        char *s_args = NULL;
 
        p = argv;
@@ -38,14 +40,20 @@ static int kexec_load(const char *l_image, const char *l_initrd,
                *p++ = s_initrd;         /* 3 */
        }
 
+       if (l_dtb) {
+               s_dtb = talloc_asprintf(NULL, "--dtb=%s", l_dtb);
+               assert(s_dtb);
+               *p++ = s_dtb;            /* 4 */
+       }
+
        if (args) {
                s_args = talloc_asprintf(NULL, "--append=%s", args);
                assert(s_args);
-               *p++ = s_args;          /* 4 */
+               *p++ = s_args;          /* 5 */
        }
 
-       *p++ = l_image;                 /* */
-       *p++ = NULL;                    /* 6 */
+       *p++ = l_image;                 /* 6*/
+       *p++ = NULL;                    /* 7 */
 
        result = pb_run_cmd(argv, 1, dry_run);
 
@@ -53,6 +61,7 @@ static int kexec_load(const char *l_image, const char *l_initrd,
                pb_log("%s: failed: (%d)\n", __func__, result);
 
        talloc_free(s_initrd);
+       talloc_free(s_dtb);
        talloc_free(s_args);
 
        return result;
@@ -128,16 +137,18 @@ static void update_status(boot_status_fn fn, void *arg, int type,
 int boot(void *ctx, struct discover_boot_option *opt, struct boot_command *cmd,
                int dry_run, boot_status_fn status_fn, void *status_arg)
 {
-       char *local_image, *local_initrd;
+       char *local_image, *local_initrd, *local_dtb;
+       struct pb_url *image, *initrd, *dtb;
        unsigned int clean_image = 0;
        unsigned int clean_initrd = 0;
-       struct pb_url *image, *initrd;
+       unsigned int clean_dtb = 0;
        char *args;
        int result;
 
        local_initrd = NULL;
        image = NULL;
        initrd = NULL;
+       dtb = NULL;
        args = NULL;
 
        if (cmd && cmd->boot_image_file) {
@@ -155,6 +166,12 @@ int boot(void *ctx, struct discover_boot_option *opt, struct boot_command *cmd,
                initrd = opt->initrd->url;
        }
 
+       if (cmd && cmd->dtb_file) {
+               dtb = pb_url_parse(opt, cmd->dtb_file);
+       } else if (opt && opt->dtb) {
+               dtb = opt->dtb->url;
+       }
+
        if (cmd && cmd->boot_args) {
                args = talloc_strdup(ctx, cmd->boot_args);
        } else if (opt && opt->option->boot_args) {
@@ -183,10 +200,23 @@ int boot(void *ctx, struct discover_boot_option *opt, struct boot_command *cmd,
                }
        }
 
+       local_dtb = NULL;
+       if (dtb) {
+               update_status(status_fn, status_arg, BOOT_STATUS_INFO,
+                               "loading device tree");
+               local_dtb = load_url(NULL, dtb, &clean_dtb);
+               if (!local_dtb) {
+                       update_status(status_fn, status_arg, BOOT_STATUS_ERROR,
+                                       "Couldn't load device tree");
+                       goto no_load;
+               }
+       }
+
        update_status(status_fn, status_arg, BOOT_STATUS_INFO,
                        "performing kexec_load");
 
-       result = kexec_load(local_image, local_initrd, args, dry_run);
+       result = kexec_load(local_image, local_initrd, local_dtb,
+                               args, dry_run);
 
        if (result) {
                update_status(status_fn, status_arg, BOOT_STATUS_ERROR,
@@ -198,9 +228,12 @@ no_load:
                unlink(local_image);
        if (clean_initrd)
                unlink(local_initrd);
+       if (clean_dtb)
+               unlink(local_dtb);
 
        talloc_free(local_image);
        talloc_free(local_initrd);
+       talloc_free(local_dtb);
 
        if (!result) {
                update_status(status_fn, status_arg, BOOT_STATUS_INFO,
index 46fecd2c15566deaa12df3a94e896c0a939e4a0d..d2a3f16757ed9433baaee15d207667190ea33634 100644 (file)
@@ -460,6 +460,7 @@ static bool __attribute__((used)) boot_option_is_resolved(
 {
        return resource_is_resolved(opt->boot_image) &&
                resource_is_resolved(opt->initrd) &&
+               resource_is_resolved(opt->dtb) &&
                resource_is_resolved(opt->icon);
 }
 
@@ -484,6 +485,7 @@ static bool boot_option_resolve(struct discover_boot_option *opt,
 {
        return resource_resolve(opt->boot_image, "boot_image", opt, handler) &&
                resource_resolve(opt->initrd, "initrd", opt, handler) &&
+               resource_resolve(opt->dtb, "dtb", opt, handler) &&
                resource_resolve(opt->icon, "icon", opt, handler);
 }
 
@@ -495,6 +497,7 @@ static void boot_option_finalise(struct device_handler *handler,
        /* check that the parsers haven't set any of the final data */
        assert(!opt->option->boot_image_file);
        assert(!opt->option->initrd_file);
+       assert(!opt->option->dtb_file);
        assert(!opt->option->icon_file);
        assert(!opt->option->device_id);
 
@@ -502,6 +505,8 @@ static void boot_option_finalise(struct device_handler *handler,
                opt->option->boot_image_file = opt->boot_image->url->full;
        if (opt->initrd)
                opt->option->initrd_file = opt->initrd->url->full;
+       if (opt->dtb)
+               opt->option->dtb_file = opt->dtb->url->full;
        if (opt->icon)
                opt->option->icon_file = opt->icon->url->full;
 
index 60a33b7bfc9107c5fba31177d794f13a5eb6313b..693f5e45a229e66a71cd069049e10486c536cdd7 100644 (file)
@@ -46,6 +46,7 @@ struct discover_boot_option {
 
        struct resource         *boot_image;
        struct resource         *initrd;
+       struct resource         *dtb;
        struct resource         *icon;
 };
 
index 4b4c2f7b49b9404ab67ecdd0e5fbb7ba4456a580..9d0322de39280e0f66a28ad9f783c419afbc12ae 100644 (file)
@@ -21,6 +21,7 @@ static void kboot_process_pair(struct conf_context *conf, const char *name,
        char *args;
        const char *initrd;
        const char *root;
+       const char *dtb;
 
        /* ignore bare values */
 
@@ -50,6 +51,7 @@ static void kboot_process_pair(struct conf_context *conf, const char *name,
        args = talloc_strdup(opt, "");
        initrd = conf_get_global_option(conf, "initrd");
        root = conf_get_global_option(conf, "root");
+       dtb = conf_get_global_option(conf, "dtb");
 
        pos = strchr(value, ' ');
 
@@ -79,6 +81,11 @@ static void kboot_process_pair(struct conf_context *conf, const char *name,
                        continue;
                }
 
+               if (streq(cl_name, "dtb")) {
+                       dtb = cl_value;
+                       continue;
+               }
+
                args = talloc_asprintf_append(args, "%s=%s ", cl_name,
                        cl_value);
        }
@@ -93,15 +100,22 @@ out_add:
        } else
                opt->boot_args = args;
 
+       opt->description = talloc_asprintf(opt, "%s %s", value,
+                       opt->boot_args);
+
        if (initrd) {
                d_opt->initrd = create_devpath_resource(d_opt,
                                conf->dc->device, initrd);
+               opt->description = talloc_asprintf_append(opt->description,
+                               " initrd=%s", initrd);
+       }
 
-               opt->description = talloc_asprintf(opt, "%s initrd=%s %s",
-                       value, initrd, opt->boot_args);
-       } else
-               opt->description = talloc_asprintf(opt, "%s %s", value,
-                       opt->boot_args);
+       if (dtb) {
+               d_opt->dtb = create_devpath_resource(d_opt,
+                               conf->dc->device, dtb);
+               opt->description = talloc_asprintf_append(opt->description,
+                               " dtb=%s", dtb);
+       }
 
        conf_strip_str(opt->boot_args);
        conf_strip_str(opt->description);
@@ -110,6 +124,7 @@ out_add:
 }
 
 static struct conf_global_option kboot_global_options[] = {
+       { .name = "dtb" },
        { .name = "initrd" },
        { .name = "root" },
        { .name = "video" },
index d3174af7994cc8937fd1ca1df9d92948f0ba5238..bcc7230a0060c062600ed69c66aadfde2cdf2f25 100644 (file)
@@ -34,6 +34,7 @@
  *    4-byte len, icon_file
  *    4-byte len, boot_image_file
  *    4-byte len, initrd_file
+ *    4-byte len, dtb_file
  *    4-byte len, boot_args
  *
  * action = 0x2: device remove message
@@ -45,6 +46,7 @@
  *   4-byte len, boot option id
  *   4-byte len, boot_image_file
  *   4-byte len, initrd_file
+ *   4-byte len, dtb_file
  *   4-byte len, boot_args
  *
  */
@@ -67,6 +69,7 @@ void pb_protocol_dump_device(const struct device *dev, const char *text,
                fprintf(stream, "%s\t\ticon: %s\n", text, opt->icon_file);
                fprintf(stream, "%s\t\tboot: %s\n", text, opt->boot_image_file);
                fprintf(stream, "%s\t\tinit: %s\n", text, opt->initrd_file);
+               fprintf(stream, "%s\t\tdtb:  %s\n", text, opt->dtb_file);
                fprintf(stream, "%s\t\targs: %s\n", text, opt->boot_args);
        }
 }
@@ -178,6 +181,7 @@ int pb_protocol_boot_option_len(const struct boot_option *opt)
                4 + optional_strlen(opt->icon_file) +
                4 + optional_strlen(opt->boot_image_file) +
                4 + optional_strlen(opt->initrd_file) +
+               4 + optional_strlen(opt->dtb_file) +
                4 + optional_strlen(opt->boot_args) +
                sizeof(opt->is_default);
 }
@@ -187,6 +191,7 @@ int pb_protocol_boot_len(const struct boot_command *boot)
        return  4 + optional_strlen(boot->option_id) +
                4 + optional_strlen(boot->boot_image_file) +
                4 + optional_strlen(boot->initrd_file) +
+               4 + optional_strlen(boot->dtb_file) +
                4 + optional_strlen(boot->boot_args);
 }
 
@@ -226,6 +231,7 @@ int pb_protocol_serialise_boot_option(const struct boot_option *opt,
        pos += pb_protocol_serialise_string(pos, opt->icon_file);
        pos += pb_protocol_serialise_string(pos, opt->boot_image_file);
        pos += pb_protocol_serialise_string(pos, opt->initrd_file);
+       pos += pb_protocol_serialise_string(pos, opt->dtb_file);
        pos += pb_protocol_serialise_string(pos, opt->boot_args);
 
        *(bool *)pos = opt->is_default;
@@ -245,6 +251,7 @@ int pb_protocol_serialise_boot_command(const struct boot_command *boot,
        pos += pb_protocol_serialise_string(pos, boot->option_id);
        pos += pb_protocol_serialise_string(pos, boot->boot_image_file);
        pos += pb_protocol_serialise_string(pos, boot->initrd_file);
+       pos += pb_protocol_serialise_string(pos, boot->dtb_file);
        pos += pb_protocol_serialise_string(pos, boot->boot_args);
 
        assert(pos <= buf + buf_len);
@@ -423,6 +430,9 @@ int pb_protocol_deserialise_boot_option(struct boot_option *opt,
        if (read_string(opt, &pos, &len, &opt->initrd_file))
                goto out;
 
+       if (read_string(opt, &pos, &len, &opt->dtb_file))
+               goto out;
+
        if (read_string(opt, &pos, &len, &opt->boot_args))
                goto out;
 
@@ -455,6 +465,9 @@ int pb_protocol_deserialise_boot_command(struct boot_command *cmd,
        if (read_string(cmd, &pos, &len, &cmd->initrd_file))
                goto out;
 
+       if (read_string(cmd, &pos, &len, &cmd->dtb_file))
+               goto out;
+
        if (read_string(cmd, &pos, &len, &cmd->boot_args))
                goto out;
 
index 5be2cb697597a3c12c177aea26644b67bc9e3dec..9fed7aaaba65d3a5948d248c6482299197cde3e9 100644 (file)
@@ -24,6 +24,7 @@ struct boot_option {
        char            *icon_file;
        char            *boot_image_file;
        char            *initrd_file;
+       char            *dtb_file;
        char            *boot_args;
        bool            is_default;
 
@@ -36,6 +37,7 @@ struct boot_command {
        char *option_id;
        char *boot_image_file;
        char *initrd_file;
+       char *dtb_file;
        char *boot_args;
 };
 
index ae5d5cd2e50b00e03cfca47b41fb6b0c8e23d0eb..c3f3f383f59fa0bf51f4d72ecf45482259a148db 100644 (file)
@@ -249,6 +249,7 @@ static void create_boot_command(struct boot_command *command,
        command->option_id = boot_option->id;
        command->boot_image_file = data->image;
        command->initrd_file = data->initrd;
+       command->dtb_file = data->dtb;
        command->boot_args = data->args;
 }
 
index 83bb9c97ea1de7b6aaa8ab6c4ac096bd029614b2..ed1f504c4e59904ecbcd9d8ac5685b7b7b757e44 100644 (file)
@@ -9,6 +9,7 @@ struct discover_client;
 struct pb_boot_data {
        char *image;
        char *initrd;
+       char *dtb;
        char *args;
 };
 
index fb0bee8ef526a9d4c6ab853072388ff13b793cef..4579b1a3852c7e4552d205b7c1ecdf666f9c8547 100644 (file)
@@ -185,6 +185,9 @@ static struct pb_boot_data *boot_editor_prepare_data(
        bd->initrd = *s ? talloc_strdup(bd, s) : NULL;
 
        s = boot_editor_chomp(field_buffer(boot_editor->fields[2], 0));
+       bd->dtb = *s ? talloc_strdup(bd, s) : NULL;
+
+       s = boot_editor_chomp(field_buffer(boot_editor->fields[3], 0));
        bd->args = *s ? talloc_strdup(bd, s) : NULL;
 
        return bd;
@@ -315,6 +318,7 @@ struct boot_editor *boot_editor_init(void *ui_ctx,
 
        pb_log("%s: image:  '%s'\n", __func__, bd->image);
        pb_log("%s: initrd: '%s'\n", __func__, bd->initrd);
+       pb_log("%s: dtb:    '%s'\n", __func__, bd->dtb);
        pb_log("%s: args:   '%s'\n", __func__, bd->args);
 
        assert(on_exit);
@@ -337,15 +341,17 @@ struct boot_editor *boot_editor_init(void *ui_ctx,
 
        boot_editor->on_exit = on_exit;
 
-       boot_editor->fields = talloc_array(boot_editor, FIELD *, 7);
+       boot_editor->fields = talloc_array(boot_editor, FIELD *, 9);
 
        boot_editor->fields[0] = boot_editor_setup_field(0, 9, bd->image);
        boot_editor->fields[1] = boot_editor_setup_field(1, 9, bd->initrd);
-       boot_editor->fields[2] = boot_editor_setup_field(2, 9, bd->args);
-       boot_editor->fields[3] = boot_editor_setup_label(0, 1, "image:");
-       boot_editor->fields[4] = boot_editor_setup_label(1, 1, "initrd:");
-       boot_editor->fields[5] = boot_editor_setup_label(2, 1, "args:");
-       boot_editor->fields[6] = NULL;
+       boot_editor->fields[2] = boot_editor_setup_field(2, 9, bd->dtb);
+       boot_editor->fields[3] = boot_editor_setup_field(3, 9, bd->args);
+       boot_editor->fields[4] = boot_editor_setup_label(0, 1, "image:");
+       boot_editor->fields[5] = boot_editor_setup_label(1, 1, "initrd:");
+       boot_editor->fields[6] = boot_editor_setup_label(2, 1, "dtb:");
+       boot_editor->fields[7] = boot_editor_setup_label(3, 1, "args:");
+       boot_editor->fields[8] = NULL;
 
        boot_editor->ncf = new_form(boot_editor->fields);
 
index 82e534db817e4f5f8e6252b25bb20fe5731d6658..1acc2f0bd0a76e57d6d8e6deb6b066fffcd87594 100644 (file)
@@ -158,6 +158,7 @@ static void cui_boot_editor_on_exit(struct boot_editor *boot_editor, enum boot_e
                pb_log("%s: updating opt '%s'\n", __func__, cod->name);
                pb_log(" image  '%s'\n", cod->bd->image);
                pb_log(" initrd '%s'\n", cod->bd->initrd);
+               pb_log(" dtb    '%s'\n", cod->bd->dtb);
                pb_log(" args   '%s'\n", cod->bd->args);
        }
 
@@ -375,6 +376,7 @@ static int cui_boot_option_add(struct device *dev, struct boot_option *opt,
 
        cod->bd->image = talloc_strdup(cod->bd, opt->boot_image_file);
        cod->bd->initrd = talloc_strdup(cod->bd, opt->initrd_file);
+       cod->bd->dtb = talloc_strdup(cod->bd, opt->dtb_file);
        cod->bd->args = talloc_strdup(cod->bd, opt->boot_args);
 
        pmenu_item_setup(cui->main, i, insert_pt, cod->name);
index b81d367ab77218c9ea958e4d076d5698c956cc27..45a4c7489719adc3f26fc106e7bef34096540e16 100644 (file)
@@ -22,6 +22,7 @@ static int print_device_add(struct device *device,
                printf("\t\ticon: %s\n", opt->icon_file);
                printf("\t\tboot: %s\n", opt->boot_image_file);
                printf("\t\tinit: %s\n", opt->initrd_file);
+               printf("\t\tdtb:  %s\n", opt->dtb_file);
                printf("\t\targs: %s\n", opt->boot_args);
        }
 
index 09d8e99c2518e5d138b3e3781b76ab7688d02afb..445c865d82ed54b7588bd4dc731afaeb13ba7f0b 100644 (file)
@@ -147,6 +147,8 @@ static int pbt_boot_option_add(struct device *dev, struct boot_option *opt,
                opt->boot_image_file);
        opt_data->bd->initrd = talloc_strdup(opt_data->bd,
                opt->initrd_file);
+       opt_data->bd->dtb = talloc_strdup(opt_data->bd,
+               opt->dtb_file);
        opt_data->bd->args = talloc_strdup(opt_data->bd,
                opt->boot_args);
        opt_data->opt = opt;