<listitem><para>Takes an absolute path, or a relative path beginning with
<filename>./</filename>. Specifies a JSON firmware definition file, which allows selecting the
firmware to boot in the VM. If not specified, a suitable firmware is automatically discovered. If the
- special string <literal>list</literal> is specified lists all discovered firmwares.</para>
+ special string <literal>list</literal> is specified lists all discovered firmwares. If the special
+ string <literal>describe</literal> is specified, the firmware that would be selected (taking
+ <option>--firmware-features=</option> into account) is printed and the program exits.</para>
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
</varlistentry>
comps=$(compgen -f -- "$cur" )
elif __contains_word "$prev" ${OPTS[FIRMWARE]}; then
compopt -o nospace -o filenames
- comps="list $(compgen -f -- "$cur" )"
+ comps="list describe $(compgen -f -- "$cur" )"
elif __contains_word "$prev" ${OPTS[FIRMWARE_FEATURES]}; then
comps='list'
elif __contains_word "$prev" ${OPTS[BIND]}; then
return 0;
}
-static int load_firmware_data(const char *path, FirmwareData **ret) {
+static int load_firmware_data(const char *path, FirmwareData **ret, sd_json_variant **ret_json) {
int r;
assert(path);
return r;
*ret = TAKE_PTR(fwd);
+
+ if (ret_json)
+ *ret_json = TAKE_PTR(json);
+
return 0;
}
STRV_FOREACH(file, conf_files) {
_cleanup_(firmware_data_freep) FirmwareData *fwd = NULL;
- r = load_firmware_data(*file, &fwd);
+ r = load_firmware_data(*file, &fwd, /* ret_json= */ NULL);
if (r < 0) {
log_debug_errno(r, "Failed to load JSON file '%s', skipping: %m", *file);
continue;
assert(path);
assert(ret);
- r = load_firmware_data(path, &fwd);
+ r = load_firmware_data(path, &fwd, /* ret_json= */ NULL);
if (r < 0)
return r;
return ovmf_config_make(fwd, ret);
}
-int find_ovmf_config(Set *features_include, Set *features_exclude, OvmfConfig **ret) {
+int find_ovmf_config(
+ Set *features_include,
+ Set *features_exclude,
+ OvmfConfig **ret,
+ sd_json_variant **ret_firmware_json) {
_cleanup_(ovmf_config_freep) OvmfConfig *config = NULL;
_cleanup_strv_free_ char **conf_files = NULL;
const char* native_arch_qemu;
STRV_FOREACH(file, conf_files) {
_cleanup_(firmware_data_freep) FirmwareData *fwd = NULL;
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *json = NULL;
- r = load_firmware_data(*file, &fwd);
+ r = load_firmware_data(*file, &fwd, ret_firmware_json ? &json : NULL);
if (r < 0) {
log_debug_errno(r, "Failed to load JSON file '%s', skipping: %m", *file);
continue;
return r;
log_debug("Selected firmware definition %s.", *file);
+
+ if (ret_firmware_json)
+ *ret_firmware_json = TAKE_PTR(json);
+
break;
}
int list_ovmf_config(char ***ret);
int list_ovmf_firmware_features(char ***ret);
int load_ovmf_config(const char *path, OvmfConfig **ret);
-int find_ovmf_config(Set *features_include, Set *features_exclude, OvmfConfig **ret);
+int find_ovmf_config(Set *features_include, Set *features_exclude, OvmfConfig **ret, sd_json_variant **ret_firmware_json);
int find_qemu_binary(char **ret_qemu_binary);
int vsock_fix_child_cid(int vhost_device_fd, unsigned *machine_cid, const char *machine);
static uid_t arg_uid_shift = UID_INVALID, arg_uid_range = 0x10000U;
static RuntimeMountContext arg_runtime_mounts = {};
static char *arg_firmware = NULL;
+static bool arg_firmware_describe = false;
static Set *arg_firmware_features_include = NULL;
static Set *arg_firmware_features_exclude = NULL;
static char *arg_forward_journal = NULL;
" --network-user-mode Use user mode networking\n"
" --secure-boot=BOOL|auto\n"
" Enable searching for firmware supporting SecureBoot\n"
- " --firmware=PATH|list Select firmware definition file (or list available)\n"
+ " --firmware=PATH|list|describe\n"
+ " Select firmware definition file (or list/describe\n"
+ " available)\n"
" --firmware-features=FEATURE[,FEATURE...]|list\n"
" Require/exclude specific firmware features\n"
" --discard-disk=BOOL Control processing of discard requests\n"
return 0;
}
+ if (streq(optarg, "describe")) {
+ /* Handled after argument parsing so that --firmware-features= is
+ * taken into account. */
+ arg_firmware = mfree(arg_firmware);
+ arg_firmware_describe = true;
+ break;
+ }
+
+ arg_firmware_describe = false;
+
if (!isempty(optarg) && !path_is_absolute(optarg) && !startswith(optarg, "./"))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Absolute path or path starting with './' required.");
if (arg_firmware)
r = load_ovmf_config(arg_firmware, &ovmf_config);
else
- r = find_ovmf_config(arg_firmware_features_include, arg_firmware_features_exclude, &ovmf_config);
+ r = find_ovmf_config(arg_firmware_features_include, arg_firmware_features_exclude, &ovmf_config, /* ret_firmware_json= */ NULL);
if (r < 0)
return log_error_errno(r, "Failed to find OVMF config: %m");
if (r <= 0)
return r;
+ if (arg_firmware_describe) {
+ _cleanup_(ovmf_config_freep) OvmfConfig *ovmf_config = NULL;
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *json = NULL;
+
+ r = find_ovmf_config(arg_firmware_features_include, arg_firmware_features_exclude, &ovmf_config, &json);
+ if (r < 0)
+ return log_error_errno(r, "Failed to find OVMF config: %m");
+
+ r = sd_json_variant_dump(json, SD_JSON_FORMAT_PRETTY|SD_JSON_FORMAT_COLOR_AUTO, stdout, /* prefix= */ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to output JSON: %m");
+
+ return 0;
+ }
+
r = determine_names();
if (r < 0)
return r;