Gerd, Corey: there's a question for you near the end, please. On 05/28/20 19:31, Philippe Mathieu-Daudé wrote: > The 'gen_id' argument refers to a QOM object able to produce > data consumable by the fw_cfg device. The producer object must > implement the FW_CFG_DATA_GENERATOR interface. > > Signed-off-by: Philippe Mathieu-Daudé <phi...@redhat.com> > --- > v7: > - renamed 'blob_id' -> 'gen_id' (danpb) > - update comment in code (lersek) > - fixed CODING_STYLE (lersek) > - use Laszlo's if (SUM(options)) != 1 { error } form > --- > softmmu/vl.c | 22 ++++++++++++++-------- > 1 file changed, 14 insertions(+), 8 deletions(-) > > diff --git a/softmmu/vl.c b/softmmu/vl.c > index ae5451bc23..cdb1d187ed 100644 > --- a/softmmu/vl.c > +++ b/softmmu/vl.c > @@ -489,6 +489,11 @@ static QemuOptsList qemu_fw_cfg_opts = { > .name = "string", > .type = QEMU_OPT_STRING, > .help = "Sets content of the blob to be inserted from a string", > + }, { > + .name = "gen_id", > + .type = QEMU_OPT_STRING, > + .help = "Sets id of the object generating the fw_cfg blob " > + "to be inserted", > }, > { /* end of list */ } > }, > @@ -2020,7 +2025,7 @@ static int parse_fw_cfg(void *opaque, QemuOpts *opts, > Error **errp) > { > gchar *buf; > size_t size; > - const char *name, *file, *str; > + const char *name, *file, *str, *gen_id; > FWCfgState *fw_cfg = (FWCfgState *) opaque; > > if (fw_cfg == NULL) { > @@ -2030,14 +2035,13 @@ static int parse_fw_cfg(void *opaque, QemuOpts *opts, > Error **errp) > name = qemu_opt_get(opts, "name"); > file = qemu_opt_get(opts, "file"); > str = qemu_opt_get(opts, "string"); > + gen_id = qemu_opt_get(opts, "gen_id"); > > - /* we need name and either a file or the content string */ > - if (!(nonempty_str(name) && (nonempty_str(file) || nonempty_str(str)))) { > - error_setg(errp, "invalid argument(s)"); > - return -1; > - } > - if (nonempty_str(file) && nonempty_str(str)) { > - error_setg(errp, "file and string are mutually exclusive"); > + /* we need the name, and exactly one of: file, content string, gen_id */ > + if (!nonempty_str(name) || > + nonempty_str(file) + nonempty_str(str) + nonempty_str(gen_id) != > 1) {
(1) I believe the indentation of this line is not correct. I think it should be out-dented by 2 spaces. > + error_setg(errp, "name, plus exactly one of file," > + " string and gen_id, are needed"); > return -1; > } > if (strlen(name) > FW_CFG_MAX_FILE_PATH - 1) { > @@ -2052,6 +2056,8 @@ static int parse_fw_cfg(void *opaque, QemuOpts *opts, > Error **errp) > if (nonempty_str(str)) { > size = strlen(str); /* NUL terminator NOT included in fw_cfg blob */ > buf = g_memdup(str, size); > + } else if (nonempty_str(gen_id)) { > + return fw_cfg_add_from_generator(fw_cfg, name, gen_id, errp); (2) This is no longer correct: fw_cfg_add_from_generator() now returns 0 on failure, but parse_fw_cfg() is supposed to return nonzer on failure. See the comment on qemu_opts_foreach() -- "parse_fw_cfg" is passed as the loop callback to qemu_opts_foreach(). Technically, we could simply write return !fw_cfg_add_from_generator(fw_cfg, name, gen_id, errp); but that wouldn't be consistent with the -1 error codes returned elsewhere from parse_fw_cfg(). So how about: size_t fw_cfg_size; fw_cfg_size = fw_cfg_add_from_generator(fw_cfg, name, gen_id, errp); return (fw_cfg_size > 0) ? 0 : -1; I think your testing may have missed this because the problem is only visible if you have *another* -fw_cfg option on the QEMU command line. Returning the wrong status code from here terminates the qemu_opts_foreach() loop, without attempting to set "error_fatal". Therefore the loop is silently terminated, thus the only symptom would be that -fw_cfg options beyond the "gen_id" one wouldn't take effect. (3) I've noticed another *potential* issue, from looking at the larger context. I apologize for missing it in v6. See commit bab47d9a75a3 ("Sort the fw_cfg file list", 2016-04-07). (I'm copying Corey; Gerd is already copied.) From that commit, we have, at the end of this function: /* For legacy, keep user files in a specific global order. */ fw_cfg_set_order_override(fw_cfg, FW_CFG_ORDER_OVERRIDE_USER); fw_cfg_add_file(fw_cfg, name, buf, size); fw_cfg_reset_order_override(fw_cfg); This takes effect for "file" and "string", but not for "gen_id". Should we apply it to "gen_id" as well? (Sorry, I really don't understand what commit bab47d9a75a3 is about!) *IF* we want to apply the same logic to "gen_id", then we should *perhaps* do, on the "nonempty_str(gen_id)" branch: size_t fw_cfg_size; fw_cfg_set_order_override(fw_cfg, FW_CFG_ORDER_OVERRIDE_USER); fw_cfg_size = fw_cfg_add_from_generator(fw_cfg, name, gen_id, errp); fw_cfg_reset_order_override(fw_cfg); return (fw_cfg_size > 0) ? 0 : -1; I think??? Or maybe even use FW_CFG_ORDER_OVERRIDE_DEVICE rather than FW_CFG_ORDER_OVERRIDE_USER? I don't have the slightest clue. (I guess if I understood what commit bab47d9a75a3 was about, I'd be less in doubt now. But that commit only hints at "avoid[ing] any future issues of moving the file creation" -- I don't know what those issues were in the first place!) With (1) optionally fixed, and (2) fixed, I'd be willing to R-b this patch; but I'm really thrown off by (3). Thanks, Laszlo > } else { > GError *err = NULL; > if (!g_file_get_contents(file, &buf, &size, &err)) { >