From c11bcba9a99e858e618f4d872a5be7d52dcaaa5a Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Mon, 15 Apr 2013 15:23:05 -0700 Subject: [PATCH] Add initial dtb support Updates & fixes by Jeremy Kerr . Signed-off-by: Geoff Levand Signed-off-by: Jeremy Kerr --- discover/boot.c | 49 +++++++++++++++++++++++++++++------ discover/device-handler.c | 5 ++++ discover/device-handler.h | 1 + discover/kboot-parser.c | 25 ++++++++++++++---- lib/pb-protocol/pb-protocol.c | 13 ++++++++++ lib/types/types.h | 2 ++ ui/common/discover-client.c | 1 + ui/common/discover-client.h | 1 + ui/ncurses/nc-boot-editor.c | 18 ++++++++----- ui/ncurses/nc-cui.c | 2 ++ ui/test/discover-test.c | 1 + ui/twin/pbt-client.c | 2 ++ 12 files changed, 101 insertions(+), 19 deletions(-) diff --git a/discover/boot.c b/discover/boot.c index 5ca69b9..c922fb6 100644 --- a/discover/boot.c +++ b/discover/boot.c @@ -16,16 +16,18 @@ * 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; /* 5 */ - *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, diff --git a/discover/device-handler.c b/discover/device-handler.c index 46fecd2..d2a3f16 100644 --- a/discover/device-handler.c +++ b/discover/device-handler.c @@ -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; diff --git a/discover/device-handler.h b/discover/device-handler.h index 60a33b7..693f5e4 100644 --- a/discover/device-handler.h +++ b/discover/device-handler.h @@ -46,6 +46,7 @@ struct discover_boot_option { struct resource *boot_image; struct resource *initrd; + struct resource *dtb; struct resource *icon; }; diff --git a/discover/kboot-parser.c b/discover/kboot-parser.c index 4b4c2f7..9d0322d 100644 --- a/discover/kboot-parser.c +++ b/discover/kboot-parser.c @@ -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" }, diff --git a/lib/pb-protocol/pb-protocol.c b/lib/pb-protocol/pb-protocol.c index d3174af..bcc7230 100644 --- a/lib/pb-protocol/pb-protocol.c +++ b/lib/pb-protocol/pb-protocol.c @@ -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; diff --git a/lib/types/types.h b/lib/types/types.h index 5be2cb6..9fed7aa 100644 --- a/lib/types/types.h +++ b/lib/types/types.h @@ -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; }; diff --git a/ui/common/discover-client.c b/ui/common/discover-client.c index ae5d5cd..c3f3f38 100644 --- a/ui/common/discover-client.c +++ b/ui/common/discover-client.c @@ -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; } diff --git a/ui/common/discover-client.h b/ui/common/discover-client.h index 83bb9c9..ed1f504 100644 --- a/ui/common/discover-client.h +++ b/ui/common/discover-client.h @@ -9,6 +9,7 @@ struct discover_client; struct pb_boot_data { char *image; char *initrd; + char *dtb; char *args; }; diff --git a/ui/ncurses/nc-boot-editor.c b/ui/ncurses/nc-boot-editor.c index fb0bee8..4579b1a 100644 --- a/ui/ncurses/nc-boot-editor.c +++ b/ui/ncurses/nc-boot-editor.c @@ -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); diff --git a/ui/ncurses/nc-cui.c b/ui/ncurses/nc-cui.c index 82e534d..1acc2f0 100644 --- a/ui/ncurses/nc-cui.c +++ b/ui/ncurses/nc-cui.c @@ -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); diff --git a/ui/test/discover-test.c b/ui/test/discover-test.c index b81d367..45a4c74 100644 --- a/ui/test/discover-test.c +++ b/ui/test/discover-test.c @@ -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); } diff --git a/ui/twin/pbt-client.c b/ui/twin/pbt-client.c index 09d8e99..445c865 100644 --- a/ui/twin/pbt-client.c +++ b/ui/twin/pbt-client.c @@ -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; -- 2.39.2