diff --git a/backends/igvm.c b/backends/igvm.c index a5a2a4eccc..80e87fe602 100644 --- a/backends/igvm.c +++ b/backends/igvm.c @@ -26,6 +26,10 @@ #include #include +#ifdef CONFIG_FDT +#include +#endif + #ifndef IGVM_VHT_OPTIONAL_BIT #define IGVM_VHT_OPTIONAL_BIT (1U << 31) #endif @@ -121,6 +125,10 @@ static int qigvm_directive_snp_id_block(QIgvm *ctx, const uint8_t *header_data, static int qigvm_initialization_guest_policy(QIgvm *ctx, const uint8_t *header_data, Error **errp); +#ifdef CONFIG_FDT +static int qigvm_directive_device_tree(QIgvm *ctx, const uint8_t *header_data, + Error **errp); +#endif struct QIGVMHandler { IgvmVariableHeaderType type; @@ -151,6 +159,10 @@ static struct QIGVMHandler handlers[] = { qigvm_initialization_guest_policy }, { IGVM_VHT_MADT, IGVM_HEADER_SECTION_DIRECTIVE, qigvm_directive_madt }, +#ifdef CONFIG_FDT + { IGVM_VHT_DEVICE_TREE, IGVM_HEADER_SECTION_DIRECTIVE, + qigvm_directive_device_tree }, +#endif }; static int qigvm_handler(QIgvm *ctx, IgvmVariableHeaderType raw_type, @@ -786,6 +798,48 @@ static int qigvm_directive_snp_id_block(QIgvm *ctx, const uint8_t *header_data, return 0; } +#ifdef CONFIG_FDT +static int qigvm_directive_device_tree(QIgvm *ctx, const uint8_t *header_data, + Error **errp) +{ + const IGVM_VHS_PARAMETER *param = (const IGVM_VHS_PARAMETER *)header_data; + g_autofree void *fdt_packed = NULL; + QIgvmParameterData *param_entry; + uint32_t fdt_size; + + param_entry = qigvm_find_param_entry(ctx, + param->parameter_area_index, errp); + if (param_entry == NULL) { + return -1; + } + + if (ctx->machine_state->fdt == NULL) { + error_setg(errp, "IGVM: device tree not available"); + return -1; + } + + fdt_size = fdt_totalsize(ctx->machine_state->fdt); + fdt_packed = g_memdup2(ctx->machine_state->fdt, fdt_size); + + if (fdt_pack(fdt_packed)) { + error_setg(errp, "IGVM: failed to pack device tree"); + return -1; + } + + fdt_size = fdt_totalsize(fdt_packed); + if (fdt_size > param_entry->size) { + error_setg(errp, + "IGVM: device tree size exceeds parameter area" + " defined in IGVM file"); + return -1; + } + + memcpy(param_entry->data, fdt_packed, fdt_size); + + return 0; +} +#endif + static int qigvm_initialization_guest_policy(QIgvm *ctx, const uint8_t *header_data, Error **errp) { diff --git a/backends/meson.build b/backends/meson.build index aabfaea5fd..8792c58c36 100644 --- a/backends/meson.build +++ b/backends/meson.build @@ -35,7 +35,7 @@ endif system_ss.add(when: gio, if_true: files('dbus-vmstate.c')) system_ss.add(when: 'CONFIG_SGX', if_true: files('hostmem-epc.c')) -system_ss.add(when: igvm, if_true: [files('igvm-cfg.c', 'igvm.c')]) +system_ss.add(when: igvm, if_true: [files('igvm-cfg.c', 'igvm.c'), fdt]) system_ss.add(when: 'CONFIG_SPDM_SOCKET', if_true: files('spdm-socket.c'))