Misc HW patch queue

- Support string data for extendPCR in VirtIO NSM device (Dorjoy)
 - Have PCI_BUS implement TYPE_FW_CFG_DATA_GENERATOR_INTERFACE (Phil)
 - Decouple AHCI from PCI (Bernhard)
 - Add status to usb_msd_packet_complete (Nick)
 - Header cleanups (Alex, Phil)
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmdcwx4ACgkQ4+MsLN6t
 wN52NRAAlFWIbtUMNt37pqUCmbf9f/rpYAfvKvMQ1h1u73VfOPdFpE9TEySj8+rm
 PM/kqsjRuTxrWreEon8SBqnKmXKSLOQ2CbB3TjCy2hlfa6vs5UtTdmzN4l1cagG5
 MtOOjh0yKUAel5DhI3NxA94HJf2dHSSY9dT+6+82eYnVNCBWvTuQp/xDq1TxsW4/
 KAD+ZFDCrUVSGqkU3ZcyHmHxuuFjo8pCfFGsCf9kHAjCxtj5M0GFjMIOcT4WAAnW
 PvAM1q84ceBx5LiObEYWu+NB95Xy3YvAjCMFNRIhS64C0SR6o+HhKo9TSprMmpW6
 ncDnNmg85SbUc5yhojvkg25D63uh5NROh9J3gqoibX+Jc1poZN/Xjt98EzqmrLiv
 cYyzs4FO5r1sdVBGrRi7iRhFui61chfTJrPbNYePRABGUgxXBjPNwTUm0OwHLdi9
 X9ehbYlYlxHqV0WGq1j47uMB5/SuyeXzYDO4im6fpk7RrpliNysa5zB1vBuDUNpR
 Bu5ypprg80km20SjFieC5R0LIT+A38H2ir2qo9buJ+wd2X/n/nqxK4Ucl1s8PLBF
 76WPLIMOV71bshlEEh6KVn+U978BsY4yPr0dZ+javNvGRzZx8ioPK+2OCT+XN39N
 oeCcTnC+9YTyYeWJqmY3Hd/kqM+32Jl7FdEEoE0EADz3fSPcvQs=
 =cxm9
 -----END PGP SIGNATURE-----

Merge tag 'hw-misc-20241214' of https://github.com/philmd/qemu into staging

Misc HW patch queue

- Support string data for extendPCR in VirtIO NSM device (Dorjoy)
- Have PCI_BUS implement TYPE_FW_CFG_DATA_GENERATOR_INTERFACE (Phil)
- Decouple AHCI from PCI (Bernhard)
- Add status to usb_msd_packet_complete (Nick)
- Header cleanups (Alex, Phil)

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmdcwx4ACgkQ4+MsLN6t
# wN52NRAAlFWIbtUMNt37pqUCmbf9f/rpYAfvKvMQ1h1u73VfOPdFpE9TEySj8+rm
# PM/kqsjRuTxrWreEon8SBqnKmXKSLOQ2CbB3TjCy2hlfa6vs5UtTdmzN4l1cagG5
# MtOOjh0yKUAel5DhI3NxA94HJf2dHSSY9dT+6+82eYnVNCBWvTuQp/xDq1TxsW4/
# KAD+ZFDCrUVSGqkU3ZcyHmHxuuFjo8pCfFGsCf9kHAjCxtj5M0GFjMIOcT4WAAnW
# PvAM1q84ceBx5LiObEYWu+NB95Xy3YvAjCMFNRIhS64C0SR6o+HhKo9TSprMmpW6
# ncDnNmg85SbUc5yhojvkg25D63uh5NROh9J3gqoibX+Jc1poZN/Xjt98EzqmrLiv
# cYyzs4FO5r1sdVBGrRi7iRhFui61chfTJrPbNYePRABGUgxXBjPNwTUm0OwHLdi9
# X9ehbYlYlxHqV0WGq1j47uMB5/SuyeXzYDO4im6fpk7RrpliNysa5zB1vBuDUNpR
# Bu5ypprg80km20SjFieC5R0LIT+A38H2ir2qo9buJ+wd2X/n/nqxK4Ucl1s8PLBF
# 76WPLIMOV71bshlEEh6KVn+U978BsY4yPr0dZ+javNvGRzZx8ioPK+2OCT+XN39N
# oeCcTnC+9YTyYeWJqmY3Hd/kqM+32Jl7FdEEoE0EADz3fSPcvQs=
# =cxm9
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 13 Dec 2024 18:28:30 EST
# gpg:                using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: FAAB E75E 1291 7221 DCFD  6BB2 E3E3 2C2C DEAD C0DE

* tag 'hw-misc-20241214' of https://github.com/philmd/qemu:
  hw/xtensa: Include missing 'exec/tswap.h' header
  hw/sh4/r2d: Include missing 'exec/tswap.h' header
  hw/mips: Include missing 'exec/tswap.h' header
  hw/ide/ahci: Extract TYPE_SYSBUS_AHCI into dedicated file
  hw/ide/ahci: Decouple from PCI
  hw/usb/hcd-xhci-pci: Indentation fix
  hw/usb/hcd-xhci-nec: Remove unused XHCINecState::flags field
  hw/usb/msd: Add status to usb_msd_packet_complete() function
  hw/net/can: clean-up unnecessary includes
  hw/nvram/fw_cfg: Remove fw_cfg_add_extra_pci_roots()
  hw: Use pci_bus_add_fw_cfg_extra_pci_roots()
  hw/pci: Add pci_bus_add_fw_cfg_extra_pci_roots() helper
  hw/pci: Have PCI_BUS implement TYPE_FW_CFG_DATA_GENERATOR_INTERFACE
  hw/nvram/fw_cfg: Skip FW_CFG_DATA_GENERATOR when no data to generate
  hw/nvram/fw_cfg: Pass QOM parent to fw_cfg_add_file_from_generator()
  hw/nvram/fw_cfg: Rename fw_cfg_add_[file]_from_generator()
  hw/riscv/virt: Remove pointless GPEX_HOST() cast
  hw/virtio/virtio-nsm: Support string data for extendPCR
  hw/core/eif: Use stateful qcrypto apis
  docs/nitro-enclave: Fix terminal commands formatting

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2024-12-14 08:42:53 -05:00
commit ca80a5d026
37 changed files with 343 additions and 358 deletions

View file

@ -48,13 +48,13 @@ Running a nitro-enclave VM
First, run `vhost-device-vsock`__ (or a similar tool that supports vhost-user-vsock). First, run `vhost-device-vsock`__ (or a similar tool that supports vhost-user-vsock).
The forward-cid option below with value 1 forwards all connections from the enclave The forward-cid option below with value 1 forwards all connections from the enclave
VM to the host machine and the forward-listen (port numbers separated by '+') is used VM to the host machine and the forward-listen (port numbers separated by '+') is used
for forwarding connections from the host machine to the enclave VM. for forwarding connections from the host machine to the enclave VM::
__ https://github.com/rust-vmm/vhost-device/tree/main/vhost-device-vsock#using-the-vsock-backend
$ vhost-device-vsock \ $ vhost-device-vsock \
--vm guest-cid=4,forward-cid=1,forward-listen=9001+9002,socket=/tmp/vhost4.socket --vm guest-cid=4,forward-cid=1,forward-listen=9001+9002,socket=/tmp/vhost4.socket
__ https://github.com/rust-vmm/vhost-device/tree/main/vhost-device-vsock#using-the-vsock-backend
Now run the necessary applications on the host machine so that the nitro-enclave VM Now run the necessary applications on the host machine so that the nitro-enclave VM
applications' vsock communication works. For example, the nitro-enclave VM's init applications' vsock communication works. For example, the nitro-enclave VM's init
process connects to CID 3 and sends a single byte hello heartbeat (0xB7) to let the process connects to CID 3 and sends a single byte hello heartbeat (0xB7) to let the
@ -65,7 +65,7 @@ the applications on the host machine that would typically be running in the pare
VM for successful communication with the enclave VM. VM for successful communication with the enclave VM.
Then run the nitro-enclave VM using the following command where ``hello.eif`` is Then run the nitro-enclave VM using the following command where ``hello.eif`` is
an EIF file you would use to spawn a real AWS nitro enclave virtual machine: an EIF file you would use to spawn a real AWS nitro enclave virtual machine::
$ qemu-system-x86_64 -M nitro-enclave,vsock=c,id=hello-world \ $ qemu-system-x86_64 -M nitro-enclave,vsock=c,id=hello-world \
-kernel hello-world.eif -nographic -m 4G --enable-kvm -cpu host \ -kernel hello-world.eif -nographic -m 4G --enable-kvm -cpu host \

View file

@ -71,7 +71,7 @@ config HIGHBANK
depends on TCG && ARM depends on TCG && ARM
select A9MPCORE select A9MPCORE
select A15MPCORE select A15MPCORE
select AHCI select AHCI_SYSBUS
select ARM_TIMER # sp804 select ARM_TIMER # sp804
select ARM_V7M select ARM_V7M
select PL011 if !HAVE_RUST # UART select PL011 if !HAVE_RUST # UART
@ -192,7 +192,7 @@ config SBSA_REF
depends on TCG && AARCH64 depends on TCG && AARCH64
imply PCI_DEVICES imply PCI_DEVICES
select DEVICE_TREE select DEVICE_TREE
select AHCI select AHCI_SYSBUS
select ARM_SMMUV3 select ARM_SMMUV3
select GPIO_KEY select GPIO_KEY
select PCI_EXPRESS select PCI_EXPRESS
@ -319,7 +319,7 @@ config ARM_V7M
config ALLWINNER_A10 config ALLWINNER_A10
bool bool
select AHCI select AHCI_SYSBUS
select ALLWINNER_A10_PIT select ALLWINNER_A10_PIT
select ALLWINNER_A10_PIC select ALLWINNER_A10_PIC
select ALLWINNER_A10_CCM select ALLWINNER_A10_CCM
@ -352,7 +352,7 @@ config ALLWINNER_H3
config ALLWINNER_R40 config ALLWINNER_R40
bool bool
default y if TCG && ARM default y if TCG && ARM
select AHCI select AHCI_SYSBUS
select ALLWINNER_SRAMC select ALLWINNER_SRAMC
select ALLWINNER_A10_PIT select ALLWINNER_A10_PIT
select ALLWINNER_WDT select ALLWINNER_WDT
@ -422,7 +422,7 @@ config XLNX_ZYNQMP_ARM
bool bool
default y if PIXMAN default y if PIXMAN
depends on TCG && AARCH64 depends on TCG && AARCH64
select AHCI select AHCI_SYSBUS
select ARM_GIC select ARM_GIC
select CADENCE select CADENCE
select CPU_CLUSTER select CPU_CLUSTER

View file

@ -1750,7 +1750,8 @@ void virt_machine_done(Notifier *notifier, void *data)
exit(1); exit(1);
} }
fw_cfg_add_extra_pci_roots(vms->bus, vms->fw_cfg); pci_bus_add_fw_cfg_extra_pci_roots(vms->fw_cfg, vms->bus,
&error_abort);
virt_acpi_setup(vms); virt_acpi_setup(vms);
virt_build_smbios(vms); virt_build_smbios(vms);

View file

@ -187,10 +187,16 @@ static void safe_unlink(char *f)
* Upon success, the caller is reponsible for unlinking and freeing *kernel_path * Upon success, the caller is reponsible for unlinking and freeing *kernel_path
*/ */
static bool read_eif_kernel(FILE *f, uint64_t size, char **kernel_path, static bool read_eif_kernel(FILE *f, uint64_t size, char **kernel_path,
uint8_t *kernel, uint32_t *crc, Error **errp) QCryptoHash *hash0, QCryptoHash *hash1,
uint32_t *crc, Error **errp)
{ {
size_t got; size_t got;
FILE *tmp_file = NULL; FILE *tmp_file = NULL;
uint8_t *kernel = g_try_malloc(size);
if (!kernel) {
error_setg(errp, "Out of memory reading kernel section");
goto cleanup;
}
*kernel_path = NULL; *kernel_path = NULL;
if (!get_tmp_file("eif-kernel-XXXXXX", kernel_path, errp)) { if (!get_tmp_file("eif-kernel-XXXXXX", kernel_path, errp)) {
@ -218,6 +224,11 @@ static bool read_eif_kernel(FILE *f, uint64_t size, char **kernel_path,
} }
*crc = crc32(*crc, kernel, size); *crc = crc32(*crc, kernel, size);
if (qcrypto_hash_update(hash0, (char *)kernel, size, errp) != 0 ||
qcrypto_hash_update(hash1, (char *)kernel, size, errp) != 0) {
goto cleanup;
}
g_free(kernel);
fclose(tmp_file); fclose(tmp_file);
return true; return true;
@ -229,10 +240,12 @@ static bool read_eif_kernel(FILE *f, uint64_t size, char **kernel_path,
g_free(*kernel_path); g_free(*kernel_path);
*kernel_path = NULL; *kernel_path = NULL;
g_free(kernel);
return false; return false;
} }
static bool read_eif_cmdline(FILE *f, uint64_t size, char *cmdline, static bool read_eif_cmdline(FILE *f, uint64_t size, char *cmdline,
QCryptoHash *hash0, QCryptoHash *hash1,
uint32_t *crc, Error **errp) uint32_t *crc, Error **errp)
{ {
size_t got = fread(cmdline, 1, size, f); size_t got = fread(cmdline, 1, size, f);
@ -242,28 +255,47 @@ static bool read_eif_cmdline(FILE *f, uint64_t size, char *cmdline,
} }
*crc = crc32(*crc, (uint8_t *)cmdline, size); *crc = crc32(*crc, (uint8_t *)cmdline, size);
if (qcrypto_hash_update(hash0, cmdline, size, errp) != 0 ||
qcrypto_hash_update(hash1, cmdline, size, errp) != 0) {
return false;
}
return true; return true;
} }
static bool read_eif_ramdisk(FILE *eif, FILE *initrd, uint64_t size, static bool read_eif_ramdisk(FILE *eif, FILE *initrd, uint64_t size,
uint8_t *ramdisk, uint32_t *crc, Error **errp) QCryptoHash *hash0, QCryptoHash *h, uint32_t *crc,
Error **errp)
{ {
size_t got; size_t got;
bool ret = false;
uint8_t *ramdisk = g_try_malloc(size);
if (!ramdisk) {
error_setg(errp, "Out of memory reading initrd section");
goto cleanup;
}
got = fread(ramdisk, 1, size, eif); got = fread(ramdisk, 1, size, eif);
if ((uint64_t) got != size) { if ((uint64_t) got != size) {
error_setg(errp, "Failed to read EIF ramdisk section data"); error_setg(errp, "Failed to read EIF ramdisk section data");
return false; goto cleanup;
} }
got = fwrite(ramdisk, 1, size, initrd); got = fwrite(ramdisk, 1, size, initrd);
if ((uint64_t) got != size) { if ((uint64_t) got != size) {
error_setg(errp, "Failed to write EIF ramdisk data to temporary file"); error_setg(errp, "Failed to write EIF ramdisk data to temporary file");
return false; goto cleanup;
} }
*crc = crc32(*crc, ramdisk, size); *crc = crc32(*crc, ramdisk, size);
return true; if (qcrypto_hash_update(hash0, (char *)ramdisk, size, errp) != 0 ||
qcrypto_hash_update(h, (char *)ramdisk, size, errp) != 0) {
goto cleanup;
}
ret = true;
cleanup:
g_free(ramdisk);
return ret;
} }
static bool get_signature_fingerprint_sha384(FILE *eif, uint64_t size, static bool get_signature_fingerprint_sha384(FILE *eif, uint64_t size,
@ -391,34 +423,10 @@ static long get_file_size(FILE *f, Error **errp)
return size; return size;
} }
static bool get_SHA384_digest(GList *list, uint8_t *digest, Error **errp) static bool get_SHA384_hash(QCryptoHash *h, uint8_t *hash, Error **errp)
{ {
size_t digest_len = QCRYPTO_HASH_DIGEST_LEN_SHA384; size_t hash_len = QCRYPTO_HASH_DIGEST_LEN_SHA384;
size_t list_len = g_list_length(list); return qcrypto_hash_finalize_bytes(h, &hash, &hash_len, errp) == 0;
struct iovec *iovec_list = g_new0(struct iovec, list_len);
bool ret = true;
GList *l;
int i;
for (i = 0, l = list; l != NULL; l = l->next, i++) {
iovec_list[i] = *(struct iovec *) l->data;
}
if (qcrypto_hash_bytesv(QCRYPTO_HASH_ALGO_SHA384, iovec_list, list_len,
&digest, &digest_len, errp) < 0) {
ret = false;
}
g_free(iovec_list);
return ret;
}
static void free_iovec(struct iovec *iov)
{
if (iov) {
g_free(iov->iov_base);
g_free(iov);
}
} }
/* /*
@ -427,8 +435,8 @@ static void free_iovec(struct iovec *iov)
*/ */
bool read_eif_file(const char *eif_path, const char *machine_initrd, bool read_eif_file(const char *eif_path, const char *machine_initrd,
char **kernel_path, char **initrd_path, char **cmdline, char **kernel_path, char **initrd_path, char **cmdline,
uint8_t *image_sha384, uint8_t *bootstrap_sha384, uint8_t *image_hash, uint8_t *bootstrap_hash,
uint8_t *app_sha384, uint8_t *fingerprint_sha384, uint8_t *app_hash, uint8_t *fingerprint_hash,
bool *signature_found, Error **errp) bool *signature_found, Error **errp)
{ {
FILE *f = NULL; FILE *f = NULL;
@ -438,18 +446,29 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
uint32_t crc = 0; uint32_t crc = 0;
EifHeader eif_header; EifHeader eif_header;
bool seen_sections[EIF_SECTION_MAX] = {false}; bool seen_sections[EIF_SECTION_MAX] = {false};
/* kernel + ramdisks + cmdline sha384 hash */ /* kernel + ramdisks + cmdline SHA384 hash */
GList *iov_PCR0 = NULL; g_autoptr(QCryptoHash) hash0 = NULL;
/* kernel + boot ramdisk + cmdline sha384 hash */ /* kernel + boot ramdisk + cmdline SHA384 hash */
GList *iov_PCR1 = NULL; g_autoptr(QCryptoHash) hash1 = NULL;
/* application ramdisk(s) hash */ /* application ramdisk(s) SHA384 hash */
GList *iov_PCR2 = NULL; g_autoptr(QCryptoHash) hash2 = NULL;
uint8_t *ptr = NULL;
struct iovec *iov_ptr = NULL;
*signature_found = false; *signature_found = false;
*kernel_path = *initrd_path = *cmdline = NULL; *kernel_path = *initrd_path = *cmdline = NULL;
hash0 = qcrypto_hash_new(QCRYPTO_HASH_ALGO_SHA384, errp);
if (!hash0) {
goto cleanup;
}
hash1 = qcrypto_hash_new(QCRYPTO_HASH_ALGO_SHA384, errp);
if (!hash1) {
goto cleanup;
}
hash2 = qcrypto_hash_new(QCRYPTO_HASH_ALGO_SHA384, errp);
if (!hash2) {
goto cleanup;
}
f = fopen(eif_path, "rb"); f = fopen(eif_path, "rb");
if (f == NULL) { if (f == NULL) {
error_setg_errno(errp, errno, "Failed to open %s", eif_path); error_setg_errno(errp, errno, "Failed to open %s", eif_path);
@ -517,21 +536,8 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
goto cleanup; goto cleanup;
} }
ptr = g_try_malloc(hdr.section_size); if (!read_eif_kernel(f, hdr.section_size, kernel_path, hash0,
if (!ptr) { hash1, &crc, errp)) {
error_setg(errp, "Out of memory reading kernel section");
goto cleanup;
}
iov_ptr = g_malloc(sizeof(struct iovec));
iov_ptr->iov_base = ptr;
iov_ptr->iov_len = hdr.section_size;
iov_PCR0 = g_list_append(iov_PCR0, iov_ptr);
iov_PCR1 = g_list_append(iov_PCR1, iov_ptr);
if (!read_eif_kernel(f, hdr.section_size, kernel_path, ptr, &crc,
errp)) {
goto cleanup; goto cleanup;
} }
@ -539,7 +545,6 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
case EIF_SECTION_CMDLINE: case EIF_SECTION_CMDLINE:
{ {
uint64_t size; uint64_t size;
uint8_t *cmdline_copy;
if (seen_sections[EIF_SECTION_CMDLINE]) { if (seen_sections[EIF_SECTION_CMDLINE]) {
error_setg(errp, "Invalid EIF image. More than 1 cmdline " error_setg(errp, "Invalid EIF image. More than 1 cmdline "
"section"); "section");
@ -551,33 +556,26 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
error_setg(errp, "Out of memory reading command line section"); error_setg(errp, "Out of memory reading command line section");
goto cleanup; goto cleanup;
} }
if (!read_eif_cmdline(f, size, *cmdline, &crc, errp)) { if (!read_eif_cmdline(f, size, *cmdline, hash0, hash1, &crc,
errp)) {
goto cleanup; goto cleanup;
} }
(*cmdline)[size] = '\0'; (*cmdline)[size] = '\0';
/*
* We make a copy of '*cmdline' for putting it in iovecs so that
* we can easily free all the iovec entries later as we cannot
* free '*cmdline' which is used by the caller.
*/
cmdline_copy = g_memdup2(*cmdline, size);
iov_ptr = g_malloc(sizeof(struct iovec));
iov_ptr->iov_base = cmdline_copy;
iov_ptr->iov_len = size;
iov_PCR0 = g_list_append(iov_PCR0, iov_ptr);
iov_PCR1 = g_list_append(iov_PCR1, iov_ptr);
break; break;
} }
case EIF_SECTION_RAMDISK: case EIF_SECTION_RAMDISK:
{ {
QCryptoHash *h = hash2;
if (!seen_sections[EIF_SECTION_RAMDISK]) { if (!seen_sections[EIF_SECTION_RAMDISK]) {
/* /*
* If this is the first time we are seeing a ramdisk section, * If this is the first time we are seeing a ramdisk section,
* we need to create the initrd temporary file. * we need to:
* 1) hash it into bootstrap (hash1) instead of app (hash2)
* along with image (hash0)
* 2) create the initrd temporary file.
*/ */
h = hash1;
if (!get_tmp_file("eif-initrd-XXXXXX", initrd_path, errp)) { if (!get_tmp_file("eif-initrd-XXXXXX", initrd_path, errp)) {
goto cleanup; goto cleanup;
} }
@ -589,29 +587,7 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
} }
} }
ptr = g_try_malloc(hdr.section_size); if (!read_eif_ramdisk(f, initrd_path_f, hdr.section_size, hash0, h,
if (!ptr) {
error_setg(errp, "Out of memory reading initrd section");
goto cleanup;
}
iov_ptr = g_malloc(sizeof(struct iovec));
iov_ptr->iov_base = ptr;
iov_ptr->iov_len = hdr.section_size;
iov_PCR0 = g_list_append(iov_PCR0, iov_ptr);
/*
* If it's the first ramdisk, we need to hash it into bootstrap
* i.e., iov_PCR1, otherwise we need to hash it into app i.e.,
* iov_PCR2.
*/
if (!seen_sections[EIF_SECTION_RAMDISK]) {
iov_PCR1 = g_list_append(iov_PCR1, iov_ptr);
} else {
iov_PCR2 = g_list_append(iov_PCR2, iov_ptr);
}
if (!read_eif_ramdisk(f, initrd_path_f, hdr.section_size, ptr,
&crc, errp)) { &crc, errp)) {
goto cleanup; goto cleanup;
} }
@ -621,7 +597,7 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
case EIF_SECTION_SIGNATURE: case EIF_SECTION_SIGNATURE:
*signature_found = true; *signature_found = true;
if (!get_signature_fingerprint_sha384(f, hdr.section_size, if (!get_signature_fingerprint_sha384(f, hdr.section_size,
fingerprint_sha384, &crc, fingerprint_hash, &crc,
errp)) { errp)) {
goto cleanup; goto cleanup;
} }
@ -692,52 +668,28 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
goto cleanup; goto cleanup;
} }
ptr = g_try_malloc(machine_initrd_size);
if (!ptr) {
error_setg(errp, "Out of memory reading initrd file");
goto cleanup;
}
iov_ptr = g_malloc(sizeof(struct iovec));
iov_ptr->iov_base = ptr;
iov_ptr->iov_len = machine_initrd_size;
iov_PCR0 = g_list_append(iov_PCR0, iov_ptr);
iov_PCR2 = g_list_append(iov_PCR2, iov_ptr);
if (!read_eif_ramdisk(machine_initrd_f, initrd_path_f, if (!read_eif_ramdisk(machine_initrd_f, initrd_path_f,
machine_initrd_size, ptr, &crc, errp)) { machine_initrd_size, hash0, hash2, &crc, errp)) {
goto cleanup; goto cleanup;
} }
} }
if (!get_SHA384_digest(iov_PCR0, image_sha384, errp)) { if (!get_SHA384_hash(hash0, image_hash, errp)) {
goto cleanup; goto cleanup;
} }
if (!get_SHA384_digest(iov_PCR1, bootstrap_sha384, errp)) { if (!get_SHA384_hash(hash1, bootstrap_hash, errp)) {
goto cleanup; goto cleanup;
} }
if (!get_SHA384_digest(iov_PCR2, app_sha384, errp)) { if (!get_SHA384_hash(hash2, app_hash, errp)) {
goto cleanup; goto cleanup;
} }
/*
* We only need to free iov_PCR0 entries because iov_PCR1 and
* iov_PCR2 iovec entries are subsets of iov_PCR0 iovec entries.
*/
g_list_free_full(iov_PCR0, (GDestroyNotify) free_iovec);
g_list_free(iov_PCR1);
g_list_free(iov_PCR2);
fclose(f); fclose(f);
fclose(initrd_path_f); fclose(initrd_path_f);
safe_fclose(machine_initrd_f); safe_fclose(machine_initrd_f);
return true; return true;
cleanup: cleanup:
g_list_free_full(iov_PCR0, (GDestroyNotify) free_iovec);
g_list_free(iov_PCR1);
g_list_free(iov_PCR2);
safe_fclose(f); safe_fclose(f);
safe_fclose(initrd_path_f); safe_fclose(initrd_path_f);
safe_fclose(machine_initrd_f); safe_fclose(machine_initrd_f);

View file

@ -240,7 +240,7 @@ static FWCfgState *create_fw_cfg(MachineState *ms, PCIBus *pci_bus,
g_memdup2(qemu_version, sizeof(qemu_version)), g_memdup2(qemu_version, sizeof(qemu_version)),
sizeof(qemu_version)); sizeof(qemu_version));
fw_cfg_add_extra_pci_roots(pci_bus, fw_cfg); pci_bus_add_fw_cfg_extra_pci_roots(fw_cfg, pci_bus, &error_abort);
return fw_cfg; return fw_cfg;
} }

View file

@ -117,13 +117,13 @@ static void nitro_enclave_machine_reset(MachineState *machine, ResetType type)
memset(ne_state->vnsm->pcrs, 0, sizeof(ne_state->vnsm->pcrs)); memset(ne_state->vnsm->pcrs, 0, sizeof(ne_state->vnsm->pcrs));
/* PCR0 */ /* PCR0 */
ne_state->vnsm->extend_pcr(ne_state->vnsm, 0, ne_state->image_sha384, ne_state->vnsm->extend_pcr(ne_state->vnsm, 0, ne_state->image_hash,
QCRYPTO_HASH_DIGEST_LEN_SHA384); QCRYPTO_HASH_DIGEST_LEN_SHA384);
/* PCR1 */ /* PCR1 */
ne_state->vnsm->extend_pcr(ne_state->vnsm, 1, ne_state->bootstrap_sha384, ne_state->vnsm->extend_pcr(ne_state->vnsm, 1, ne_state->bootstrap_hash,
QCRYPTO_HASH_DIGEST_LEN_SHA384); QCRYPTO_HASH_DIGEST_LEN_SHA384);
/* PCR2 */ /* PCR2 */
ne_state->vnsm->extend_pcr(ne_state->vnsm, 2, ne_state->app_sha384, ne_state->vnsm->extend_pcr(ne_state->vnsm, 2, ne_state->app_hash,
QCRYPTO_HASH_DIGEST_LEN_SHA384); QCRYPTO_HASH_DIGEST_LEN_SHA384);
/* PCR3 */ /* PCR3 */
if (ne_state->parent_role) { if (ne_state->parent_role) {
@ -140,7 +140,7 @@ static void nitro_enclave_machine_reset(MachineState *machine, ResetType type)
/* PCR8 */ /* PCR8 */
if (ne_state->signature_found) { if (ne_state->signature_found) {
ne_state->vnsm->extend_pcr(ne_state->vnsm, 8, ne_state->vnsm->extend_pcr(ne_state->vnsm, 8,
ne_state->fingerprint_sha384, ne_state->fingerprint_hash,
QCRYPTO_HASH_DIGEST_LEN_SHA384); QCRYPTO_HASH_DIGEST_LEN_SHA384);
} }
@ -173,8 +173,8 @@ static void x86_load_eif(X86MachineState *x86ms, FWCfgState *fw_cfg,
if (!read_eif_file(machine->kernel_filename, machine->initrd_filename, if (!read_eif_file(machine->kernel_filename, machine->initrd_filename,
&eif_kernel, &eif_initrd, &eif_cmdline, &eif_kernel, &eif_initrd, &eif_cmdline,
nems->image_sha384, nems->bootstrap_sha384, nems->image_hash, nems->bootstrap_hash,
nems->app_sha384, nems->fingerprint_sha384, nems->app_hash, nems->fingerprint_hash,
&(nems->signature_found), &err)) { &(nems->signature_found), &err)) {
error_report_err(err); error_report_err(err);
exit(1); exit(1);

View file

@ -631,7 +631,8 @@ void pc_machine_done(Notifier *notifier, void *data)
/* set the number of CPUs */ /* set the number of CPUs */
x86_rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus); x86_rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus);
fw_cfg_add_extra_pci_roots(pcms->pcibus, x86ms->fw_cfg); pci_bus_add_fw_cfg_extra_pci_roots(x86ms->fw_cfg, pcms->pcibus,
&error_abort);
acpi_setup(); acpi_setup();
if (x86ms->fw_cfg) { if (x86ms->fw_cfg) {

View file

@ -54,6 +54,10 @@ config AHCI_ICH9
depends on PCI depends on PCI
select AHCI select AHCI
config AHCI_SYSBUS
bool
select AHCI
config IDE_SII3112 config IDE_SII3112
bool bool
select IDE_PCI select IDE_PCI

View file

@ -25,7 +25,6 @@
#define HW_IDE_AHCI_INTERNAL_H #define HW_IDE_AHCI_INTERNAL_H
#include "hw/ide/ahci.h" #include "hw/ide/ahci.h"
#include "hw/pci/pci_device.h"
#include "ide-internal.h" #include "ide-internal.h"
#define AHCI_MEM_BAR_SIZE 0x1000 #define AHCI_MEM_BAR_SIZE 0x1000

91
hw/ide/ahci-sysbus.c Normal file
View file

@ -0,0 +1,91 @@
/*
* QEMU AHCI Emulation (MMIO-mapped devices)
*
* Copyright (c) 2010 qiaochong@loongson.cn
* Copyright (c) 2010 Roland Elek <elek.roland@gmail.com>
* Copyright (c) 2010 Sebastian Herbszt <herbszt@gmx.de>
* Copyright (c) 2010 Alexander Graf <agraf@suse.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include "qemu/osdep.h"
#include "exec/address-spaces.h"
#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
#include "hw/ide/ahci-sysbus.h"
#include "ahci-internal.h"
static const VMStateDescription vmstate_sysbus_ahci = {
.name = "sysbus-ahci",
.fields = (const VMStateField[]) {
VMSTATE_AHCI(ahci, SysbusAHCIState),
VMSTATE_END_OF_LIST()
},
};
static void sysbus_ahci_reset(DeviceState *dev)
{
SysbusAHCIState *s = SYSBUS_AHCI(dev);
ahci_reset(&s->ahci);
}
static void sysbus_ahci_init(Object *obj)
{
SysbusAHCIState *s = SYSBUS_AHCI(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
ahci_init(&s->ahci, DEVICE(obj));
sysbus_init_mmio(sbd, &s->ahci.mem);
sysbus_init_irq(sbd, &s->ahci.irq);
}
static void sysbus_ahci_realize(DeviceState *dev, Error **errp)
{
SysbusAHCIState *s = SYSBUS_AHCI(dev);
ahci_realize(&s->ahci, dev, &address_space_memory);
}
static Property sysbus_ahci_properties[] = {
DEFINE_PROP_UINT32("num-ports", SysbusAHCIState, ahci.ports, 1),
DEFINE_PROP_END_OF_LIST(),
};
static void sysbus_ahci_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = sysbus_ahci_realize;
dc->vmsd = &vmstate_sysbus_ahci;
device_class_set_props(dc, sysbus_ahci_properties);
device_class_set_legacy_reset(dc, sysbus_ahci_reset);
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
static const TypeInfo sysbus_ahci_types[] = {
{
.name = TYPE_SYSBUS_AHCI,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(SysbusAHCIState),
.instance_init = sysbus_ahci_init,
.class_init = sysbus_ahci_class_init,
},
};
DEFINE_TYPES(sysbus_ahci_types)

View file

@ -23,20 +23,13 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "hw/irq.h" #include "hw/irq.h"
#include "hw/pci/msi.h"
#include "hw/pci/pci.h"
#include "hw/qdev-properties.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qemu/log.h" #include "qemu/log.h"
#include "qemu/main-loop.h" #include "qemu/main-loop.h"
#include "qemu/module.h"
#include "sysemu/block-backend.h" #include "sysemu/block-backend.h"
#include "sysemu/dma.h" #include "sysemu/dma.h"
#include "hw/ide/pci.h"
#include "hw/ide/ahci-pci.h"
#include "hw/ide/ahci-sysbus.h"
#include "ahci-internal.h" #include "ahci-internal.h"
#include "ide-internal.h" #include "ide-internal.h"
@ -179,34 +172,6 @@ static uint32_t ahci_port_read(AHCIState *s, int port, int offset)
return val; return val;
} }
static void ahci_irq_raise(AHCIState *s)
{
DeviceState *dev_state = s->container;
PCIDevice *pci_dev = (PCIDevice *) object_dynamic_cast(OBJECT(dev_state),
TYPE_PCI_DEVICE);
trace_ahci_irq_raise(s);
if (pci_dev && msi_enabled(pci_dev)) {
msi_notify(pci_dev, 0);
} else {
qemu_irq_raise(s->irq);
}
}
static void ahci_irq_lower(AHCIState *s)
{
DeviceState *dev_state = s->container;
PCIDevice *pci_dev = (PCIDevice *) object_dynamic_cast(OBJECT(dev_state),
TYPE_PCI_DEVICE);
trace_ahci_irq_lower(s);
if (!pci_dev || !msi_enabled(pci_dev)) {
qemu_irq_lower(s->irq);
}
}
static void ahci_check_irq(AHCIState *s) static void ahci_check_irq(AHCIState *s)
{ {
int i; int i;
@ -222,9 +187,11 @@ static void ahci_check_irq(AHCIState *s)
trace_ahci_check_irq(s, old_irq, s->control_regs.irqstatus); trace_ahci_check_irq(s, old_irq, s->control_regs.irqstatus);
if (s->control_regs.irqstatus && if (s->control_regs.irqstatus &&
(s->control_regs.ghc & HOST_CTL_IRQ_EN)) { (s->control_regs.ghc & HOST_CTL_IRQ_EN)) {
ahci_irq_raise(s); trace_ahci_irq_raise(s);
qemu_irq_raise(s->irq);
} else { } else {
ahci_irq_lower(s); trace_ahci_irq_lower(s);
qemu_irq_lower(s->irq);
} }
} }
@ -1608,7 +1575,6 @@ static const IDEDMAOps ahci_dma_ops = {
void ahci_init(AHCIState *s, DeviceState *qdev) void ahci_init(AHCIState *s, DeviceState *qdev)
{ {
s->container = qdev;
/* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */ /* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
memory_region_init_io(&s->mem, OBJECT(qdev), &ahci_mem_ops, s, memory_region_init_io(&s->mem, OBJECT(qdev), &ahci_mem_ops, s,
"ahci", AHCI_MEM_BAR_SIZE); "ahci", AHCI_MEM_BAR_SIZE);
@ -1834,70 +1800,6 @@ const VMStateDescription vmstate_ahci = {
}, },
}; };
static const VMStateDescription vmstate_sysbus_ahci = {
.name = "sysbus-ahci",
.fields = (const VMStateField[]) {
VMSTATE_AHCI(ahci, SysbusAHCIState),
VMSTATE_END_OF_LIST()
},
};
static void sysbus_ahci_reset(DeviceState *dev)
{
SysbusAHCIState *s = SYSBUS_AHCI(dev);
ahci_reset(&s->ahci);
}
static void sysbus_ahci_init(Object *obj)
{
SysbusAHCIState *s = SYSBUS_AHCI(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
ahci_init(&s->ahci, DEVICE(obj));
sysbus_init_mmio(sbd, &s->ahci.mem);
sysbus_init_irq(sbd, &s->ahci.irq);
}
static void sysbus_ahci_realize(DeviceState *dev, Error **errp)
{
SysbusAHCIState *s = SYSBUS_AHCI(dev);
ahci_realize(&s->ahci, dev, &address_space_memory);
}
static Property sysbus_ahci_properties[] = {
DEFINE_PROP_UINT32("num-ports", SysbusAHCIState, ahci.ports, 1),
DEFINE_PROP_END_OF_LIST(),
};
static void sysbus_ahci_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = sysbus_ahci_realize;
dc->vmsd = &vmstate_sysbus_ahci;
device_class_set_props(dc, sysbus_ahci_properties);
device_class_set_legacy_reset(dc, sysbus_ahci_reset);
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
static const TypeInfo sysbus_ahci_info = {
.name = TYPE_SYSBUS_AHCI,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(SysbusAHCIState),
.instance_init = sysbus_ahci_init,
.class_init = sysbus_ahci_class_init,
};
static void sysbus_ahci_register_types(void)
{
type_register_static(&sysbus_ahci_info);
}
type_init(sysbus_ahci_register_types)
void ahci_ide_create_devs(AHCIState *ahci, DriveInfo **hd) void ahci_ide_create_devs(AHCIState *ahci, DriveInfo **hd)
{ {
int i; int i;

View file

@ -61,7 +61,6 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "hw/irq.h"
#include "hw/pci/msi.h" #include "hw/pci/msi.h"
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"
@ -91,6 +90,19 @@ static const VMStateDescription vmstate_ich9_ahci = {
}, },
}; };
static void pci_ich9_ahci_update_irq(void *opaque, int irq_num, int level)
{
PCIDevice *pci_dev = opaque;
if (msi_enabled(pci_dev)) {
if (level) {
msi_notify(pci_dev, 0);
}
} else {
pci_set_irq(pci_dev, level);
}
}
static void pci_ich9_reset(DeviceState *dev) static void pci_ich9_reset(DeviceState *dev)
{ {
AHCIPCIState *d = ICH9_AHCI(dev); AHCIPCIState *d = ICH9_AHCI(dev);
@ -102,7 +114,9 @@ static void pci_ich9_ahci_init(Object *obj)
{ {
AHCIPCIState *d = ICH9_AHCI(obj); AHCIPCIState *d = ICH9_AHCI(obj);
qemu_init_irq(&d->irq, pci_ich9_ahci_update_irq, d, 0);
ahci_init(&d->ahci, DEVICE(obj)); ahci_init(&d->ahci, DEVICE(obj));
d->ahci.irq = &d->irq;
} }
static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp) static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp)
@ -125,8 +139,6 @@ static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp)
/* XXX Software should program this register */ /* XXX Software should program this register */
dev->config[0x90] = 1 << 6; /* Address Map Register - AHCI mode */ dev->config[0x90] = 1 << 6; /* Address Map Register - AHCI mode */
d->ahci.irq = pci_allocate_irq(dev);
pci_register_bar(dev, ICH9_IDP_BAR, PCI_BASE_ADDRESS_SPACE_IO, pci_register_bar(dev, ICH9_IDP_BAR, PCI_BASE_ADDRESS_SPACE_IO,
&d->ahci.idp); &d->ahci.idp);
pci_register_bar(dev, ICH9_MEM_BAR, PCI_BASE_ADDRESS_SPACE_MEMORY, pci_register_bar(dev, ICH9_MEM_BAR, PCI_BASE_ADDRESS_SPACE_MEMORY,
@ -161,7 +173,6 @@ static void pci_ich9_uninit(PCIDevice *dev)
msi_uninit(dev); msi_uninit(dev);
ahci_uninit(&d->ahci); ahci_uninit(&d->ahci);
qemu_free_irq(d->ahci.irq);
} }
static void ich_ahci_class_init(ObjectClass *klass, void *data) static void ich_ahci_class_init(ObjectClass *klass, void *data)

View file

@ -1,5 +1,6 @@
system_ss.add(when: 'CONFIG_AHCI', if_true: files('ahci.c')) system_ss.add(when: 'CONFIG_AHCI', if_true: files('ahci.c'))
system_ss.add(when: 'CONFIG_AHCI_ICH9', if_true: files('ich.c')) system_ss.add(when: 'CONFIG_AHCI_ICH9', if_true: files('ich.c'))
system_ss.add(when: 'CONFIG_AHCI_SYSBUS', if_true: files('ahci-sysbus.c'))
system_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: files('ahci-allwinner.c')) system_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: files('ahci-allwinner.c'))
system_ss.add(when: 'CONFIG_IDE_BUS', if_true: files('ide-bus.c')) system_ss.add(when: 'CONFIG_IDE_BUS', if_true: files('ide-bus.c'))
system_ss.add(when: 'CONFIG_IDE_CF', if_true: files('cf.c')) system_ss.add(when: 'CONFIG_IDE_CF', if_true: files('cf.c'))

View file

@ -40,6 +40,7 @@
#include "sysemu/reset.h" #include "sysemu/reset.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "exec/tswap.h"
#define ENVP_PADDR 0x2000 #define ENVP_PADDR 0x2000
#define ENVP_VADDR cpu_mips_phys_to_kseg0(NULL, ENVP_PADDR) #define ENVP_VADDR cpu_mips_phys_to_kseg0(NULL, ENVP_PADDR)

View file

@ -28,6 +28,7 @@
#include "qemu/datadir.h" #include "qemu/datadir.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "qemu/guest-random.h" #include "qemu/guest-random.h"
#include "exec/tswap.h"
#include "hw/clock.h" #include "hw/clock.h"
#include "hw/southbridge/piix.h" #include "hw/southbridge/piix.h"
#include "hw/isa/superio.h" #include "hw/isa/superio.h"

View file

@ -30,12 +30,8 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/event_notifier.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "qemu/thread.h"
#include "qemu/sockets.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "chardev/char.h"
#include "hw/irq.h" #include "hw/irq.h"
#include "hw/pci/pci_device.h" #include "hw/pci/pci_device.h"
#include "hw/qdev-properties.h" #include "hw/qdev-properties.h"

View file

@ -26,12 +26,8 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/event_notifier.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "qemu/thread.h"
#include "qemu/sockets.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "chardev/char.h"
#include "hw/irq.h" #include "hw/irq.h"
#include "hw/pci/pci_device.h" #include "hw/pci/pci_device.h"
#include "hw/qdev-properties.h" #include "hw/qdev-properties.h"

View file

@ -26,12 +26,8 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/event_notifier.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "qemu/thread.h"
#include "qemu/sockets.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "chardev/char.h"
#include "hw/irq.h" #include "hw/irq.h"
#include "hw/pci/pci_device.h" #include "hw/pci/pci_device.h"
#include "hw/qdev-properties.h" #include "hw/qdev-properties.h"

View file

@ -27,7 +27,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/log.h" #include "qemu/log.h"
#include "chardev/char.h" #include "qemu/bitops.h"
#include "hw/irq.h" #include "hw/irq.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "net/can_emu.h" #include "net/can_emu.h"

View file

@ -28,7 +28,8 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/log.h" #include "qemu/log.h"
#include "chardev/char.h" #include "qemu/bswap.h"
#include "qemu/bitops.h"
#include "hw/irq.h" #include "hw/irq.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "net/can_emu.h" #include "net/can_emu.h"

View file

@ -27,12 +27,8 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/event_notifier.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "qemu/thread.h"
#include "qemu/sockets.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "chardev/char.h"
#include "hw/irq.h" #include "hw/irq.h"
#include "hw/pci/pci_device.h" #include "hw/pci/pci_device.h"
#include "hw/qdev-properties.h" #include "hw/qdev-properties.h"

View file

@ -41,7 +41,6 @@
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "hw/acpi/aml-build.h" #include "hw/acpi/aml-build.h"
#include "hw/pci/pci_bus.h"
#include "hw/loader.h" #include "hw/loader.h"
#define FW_CFG_FILE_SLOTS_DFLT 0x20 #define FW_CFG_FILE_SLOTS_DFLT 0x20
@ -1027,27 +1026,29 @@ void *fw_cfg_modify_file(FWCfgState *s, const char *filename,
return NULL; return NULL;
} }
bool fw_cfg_add_from_generator(FWCfgState *s, const char *filename, bool fw_cfg_add_file_from_generator(FWCfgState *s,
const char *gen_id, Error **errp) Object *parent, const char *part,
const char *filename, Error **errp)
{ {
ERRP_GUARD();
FWCfgDataGeneratorClass *klass; FWCfgDataGeneratorClass *klass;
GByteArray *array; GByteArray *array;
Object *obj; Object *obj;
gsize size; gsize size;
obj = object_resolve_path_component(object_get_objects_root(), gen_id); obj = object_resolve_path_component(parent, part);
if (!obj) { if (!obj) {
error_setg(errp, "Cannot find object ID '%s'", gen_id); error_setg(errp, "Cannot find object ID '%s'", part);
return false; return false;
} }
if (!object_dynamic_cast(obj, TYPE_FW_CFG_DATA_GENERATOR_INTERFACE)) { if (!object_dynamic_cast(obj, TYPE_FW_CFG_DATA_GENERATOR_INTERFACE)) {
error_setg(errp, "Object ID '%s' is not a '%s' subclass", error_setg(errp, "Object ID '%s' is not a '%s' subclass",
gen_id, TYPE_FW_CFG_DATA_GENERATOR_INTERFACE); part, TYPE_FW_CFG_DATA_GENERATOR_INTERFACE);
return false; return false;
} }
klass = FW_CFG_DATA_GENERATOR_GET_CLASS(obj); klass = FW_CFG_DATA_GENERATOR_GET_CLASS(obj);
array = klass->get_data(obj, errp); array = klass->get_data(obj, errp);
if (!array) { if (*errp || !array) {
return false; return false;
} }
size = array->len; size = array->len;
@ -1056,28 +1057,6 @@ bool fw_cfg_add_from_generator(FWCfgState *s, const char *filename,
return true; return true;
} }
void fw_cfg_add_extra_pci_roots(PCIBus *bus, FWCfgState *s)
{
int extra_hosts = 0;
if (!bus) {
return;
}
QLIST_FOREACH(bus, &bus->child, sibling) {
/* look for expander root buses */
if (pci_bus_is_root(bus)) {
extra_hosts++;
}
}
if (extra_hosts && s) {
uint64_t *val = g_malloc(sizeof(*val));
*val = cpu_to_le64(extra_hosts);
fw_cfg_add_file(s, "etc/extra-pci-roots", val, sizeof(*val));
}
}
static void fw_cfg_machine_reset(void *opaque) static void fw_cfg_machine_reset(void *opaque)
{ {
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());

View file

@ -46,6 +46,7 @@
#include "hw/pci/msix.h" #include "hw/pci/msix.h"
#include "hw/hotplug.h" #include "hw/hotplug.h"
#include "hw/boards.h" #include "hw/boards.h"
#include "hw/nvram/fw_cfg.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "pci-internal.h" #include "pci-internal.h"
@ -216,11 +217,57 @@ static uint16_t pcibus_numa_node(PCIBus *bus)
return NUMA_NODE_UNASSIGNED; return NUMA_NODE_UNASSIGNED;
} }
bool pci_bus_add_fw_cfg_extra_pci_roots(FWCfgState *fw_cfg,
PCIBus *bus,
Error **errp)
{
Object *obj;
if (!bus) {
return true;
}
obj = OBJECT(bus);
return fw_cfg_add_file_from_generator(fw_cfg, obj->parent,
object_get_canonical_path_component(obj),
"etc/extra-pci-roots", errp);
}
static GByteArray *pci_bus_fw_cfg_gen_data(Object *obj, Error **errp)
{
PCIBus *bus = PCI_BUS(obj);
GByteArray *byte_array;
uint64_t extra_hosts = 0;
if (!bus) {
return NULL;
}
QLIST_FOREACH(bus, &bus->child, sibling) {
/* look for expander root buses */
if (pci_bus_is_root(bus)) {
extra_hosts++;
}
}
if (!extra_hosts) {
return NULL;
}
extra_hosts = cpu_to_le64(extra_hosts);
byte_array = g_byte_array_new();
g_byte_array_append(byte_array,
(const void *)&extra_hosts, sizeof(extra_hosts));
return byte_array;
}
static void pci_bus_class_init(ObjectClass *klass, void *data) static void pci_bus_class_init(ObjectClass *klass, void *data)
{ {
BusClass *k = BUS_CLASS(klass); BusClass *k = BUS_CLASS(klass);
PCIBusClass *pbc = PCI_BUS_CLASS(klass); PCIBusClass *pbc = PCI_BUS_CLASS(klass);
ResettableClass *rc = RESETTABLE_CLASS(klass); ResettableClass *rc = RESETTABLE_CLASS(klass);
FWCfgDataGeneratorClass *fwgc = FW_CFG_DATA_GENERATOR_CLASS(klass);
k->print_dev = pcibus_dev_print; k->print_dev = pcibus_dev_print;
k->get_dev_path = pcibus_get_dev_path; k->get_dev_path = pcibus_get_dev_path;
@ -232,6 +279,8 @@ static void pci_bus_class_init(ObjectClass *klass, void *data)
pbc->bus_num = pcibus_num; pbc->bus_num = pcibus_num;
pbc->numa_node = pcibus_numa_node; pbc->numa_node = pcibus_numa_node;
fwgc->get_data = pci_bus_fw_cfg_gen_data;
} }
static const TypeInfo pci_bus_info = { static const TypeInfo pci_bus_info = {
@ -240,6 +289,10 @@ static const TypeInfo pci_bus_info = {
.instance_size = sizeof(PCIBus), .instance_size = sizeof(PCIBus),
.class_size = sizeof(PCIBusClass), .class_size = sizeof(PCIBusClass),
.class_init = pci_bus_class_init, .class_init = pci_bus_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_FW_CFG_DATA_GENERATOR_INTERFACE },
{ }
}
}; };
static const TypeInfo cxl_interface_info = { static const TypeInfo cxl_interface_info = {

View file

@ -1140,23 +1140,21 @@ static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem,
dev = qdev_new(TYPE_GPEX_HOST); dev = qdev_new(TYPE_GPEX_HOST);
/* Set GPEX object properties for the virt machine */ /* Set GPEX object properties for the virt machine */
object_property_set_uint(OBJECT(GPEX_HOST(dev)), PCI_HOST_ECAM_BASE, object_property_set_uint(OBJECT(dev), PCI_HOST_ECAM_BASE,
ecam_base, NULL); ecam_base, NULL);
object_property_set_int(OBJECT(GPEX_HOST(dev)), PCI_HOST_ECAM_SIZE, object_property_set_int(OBJECT(dev), PCI_HOST_ECAM_SIZE,
ecam_size, NULL); ecam_size, NULL);
object_property_set_uint(OBJECT(GPEX_HOST(dev)), object_property_set_uint(OBJECT(dev), PCI_HOST_BELOW_4G_MMIO_BASE,
PCI_HOST_BELOW_4G_MMIO_BASE,
mmio_base, NULL); mmio_base, NULL);
object_property_set_int(OBJECT(GPEX_HOST(dev)), PCI_HOST_BELOW_4G_MMIO_SIZE, object_property_set_int(OBJECT(dev), PCI_HOST_BELOW_4G_MMIO_SIZE,
mmio_size, NULL); mmio_size, NULL);
object_property_set_uint(OBJECT(GPEX_HOST(dev)), object_property_set_uint(OBJECT(dev), PCI_HOST_ABOVE_4G_MMIO_BASE,
PCI_HOST_ABOVE_4G_MMIO_BASE,
high_mmio_base, NULL); high_mmio_base, NULL);
object_property_set_int(OBJECT(GPEX_HOST(dev)), PCI_HOST_ABOVE_4G_MMIO_SIZE, object_property_set_int(OBJECT(dev), PCI_HOST_ABOVE_4G_MMIO_SIZE,
high_mmio_size, NULL); high_mmio_size, NULL);
object_property_set_uint(OBJECT(GPEX_HOST(dev)), PCI_HOST_PIO_BASE, object_property_set_uint(OBJECT(dev), PCI_HOST_PIO_BASE,
pio_base, NULL); pio_base, NULL);
object_property_set_int(OBJECT(GPEX_HOST(dev)), PCI_HOST_PIO_SIZE, object_property_set_int(OBJECT(dev), PCI_HOST_PIO_SIZE,
pio_size, NULL); pio_size, NULL);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
@ -1189,7 +1187,7 @@ static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem,
gpex_set_irq_num(GPEX_HOST(dev), i, PCIE_IRQ + i); gpex_set_irq_num(GPEX_HOST(dev), i, PCIE_IRQ + i);
} }
GPEX_HOST(dev)->gpex_cfg.bus = PCI_HOST_BRIDGE(GPEX_HOST(dev))->bus; GPEX_HOST(dev)->gpex_cfg.bus = PCI_HOST_BRIDGE(dev)->bus;
return dev; return dev;
} }

View file

@ -43,6 +43,7 @@
#include "hw/loader.h" #include "hw/loader.h"
#include "hw/usb.h" #include "hw/usb.h"
#include "hw/block/flash.h" #include "hw/block/flash.h"
#include "exec/tswap.h"
#define FLASH_BASE 0x00000000 #define FLASH_BASE 0x00000000
#define FLASH_SIZE (16 * MiB) #define FLASH_SIZE (16 * MiB)

View file

@ -177,7 +177,7 @@ static const USBDesc desc = {
.str = desc_strings, .str = desc_strings,
}; };
static void usb_msd_packet_complete(MSDState *s) static void usb_msd_packet_complete(MSDState *s, int status)
{ {
USBPacket *p = s->packet; USBPacket *p = s->packet;
@ -187,6 +187,7 @@ static void usb_msd_packet_complete(MSDState *s)
* usb_packet_complete returns. * usb_packet_complete returns.
*/ */
trace_usb_msd_packet_complete(); trace_usb_msd_packet_complete();
p->status = status;
s->packet = NULL; s->packet = NULL;
usb_packet_complete(&s->dev, p); usb_packet_complete(&s->dev, p);
} }
@ -196,8 +197,7 @@ static void usb_msd_fatal_error(MSDState *s)
trace_usb_msd_fatal_error(); trace_usb_msd_fatal_error();
if (s->packet) { if (s->packet) {
s->packet->status = USB_RET_STALL; usb_msd_packet_complete(s, USB_RET_STALL);
usb_msd_packet_complete(s);
} }
/* /*
@ -255,8 +255,8 @@ void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
usb_msd_copy_data(s, p); usb_msd_copy_data(s, p);
p = s->packet; p = s->packet;
if (p && p->actual_length == p->iov.size) { if (p && p->actual_length == p->iov.size) {
p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */ /* USB_RET_SUCCESS status clears previous ASYNC status */
usb_msd_packet_complete(s); usb_msd_packet_complete(s, USB_RET_SUCCESS);
} }
} }
} }
@ -295,8 +295,8 @@ void usb_msd_command_complete(SCSIRequest *req, size_t resid)
s->mode = USB_MSDM_CSW; s->mode = USB_MSDM_CSW;
} }
} }
p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */ /* USB_RET_SUCCESS status clears previous ASYNC status */
usb_msd_packet_complete(s); usb_msd_packet_complete(s, USB_RET_SUCCESS);
} else if (s->data_len == 0) { } else if (s->data_len == 0) {
s->mode = USB_MSDM_CSW; s->mode = USB_MSDM_CSW;
} }
@ -332,8 +332,7 @@ void usb_msd_handle_reset(USBDevice *dev)
assert(s->req == NULL); assert(s->req == NULL);
if (s->packet) { if (s->packet) {
s->packet->status = USB_RET_STALL; usb_msd_packet_complete(s, USB_RET_STALL);
usb_msd_packet_complete(s);
} }
memset(&s->csw, 0, sizeof(s->csw)); memset(&s->csw, 0, sizeof(s->csw));

View file

@ -30,10 +30,8 @@
OBJECT_DECLARE_SIMPLE_TYPE(XHCINecState, NEC_XHCI) OBJECT_DECLARE_SIMPLE_TYPE(XHCINecState, NEC_XHCI)
struct XHCINecState { struct XHCINecState {
/*< private >*/
XHCIPciState parent_obj; XHCIPciState parent_obj;
/*< public >*/
uint32_t flags;
uint32_t intrs; uint32_t intrs;
uint32_t slots; uint32_t slots;
}; };
@ -51,7 +49,6 @@ static void nec_xhci_instance_init(Object *obj)
XHCIPciState *pci = XHCI_PCI(obj); XHCIPciState *pci = XHCI_PCI(obj);
XHCINecState *nec = NEC_XHCI(obj); XHCINecState *nec = NEC_XHCI(obj);
pci->xhci.flags = nec->flags;
pci->xhci.numintrs = nec->intrs; pci->xhci.numintrs = nec->intrs;
pci->xhci.numslots = nec->slots; pci->xhci.numslots = nec->slots;
} }

View file

@ -94,7 +94,7 @@ static int xhci_pci_vmstate_post_load(void *opaque, int version_id)
PCIDevice *pci_dev = PCI_DEVICE(s); PCIDevice *pci_dev = PCI_DEVICE(s);
int intr; int intr;
for (intr = 0; intr < s->xhci.numintrs; intr++) { for (intr = 0; intr < s->xhci.numintrs; intr++) {
if (s->xhci.intr[intr].msix_used) { if (s->xhci.intr[intr].msix_used) {
msix_vector_use(pci_dev, intr); msix_vector_use(pci_dev, intr);
} else { } else {

View file

@ -444,7 +444,7 @@ static bool handle_describe_pcr(VirtIONSM *vnsm, struct iovec *request,
* key = String("index"), * key = String("index"),
* value = Uint8(pcr), * value = Uint8(pcr),
* key = String("data"), * key = String("data"),
* value = Byte_String(data), * value = Byte_String(data) || String(data),
* } * }
* } * }
* } * }
@ -504,14 +504,21 @@ static enum NSMResponseTypes get_nsm_extend_pcr_req(uint8_t *req, size_t len,
if (cbor_string_length(pair[i].key) == 4 && if (cbor_string_length(pair[i].key) == 4 &&
memcmp(str, "data", 4) == 0) { memcmp(str, "data", 4) == 0) {
if (!cbor_isa_bytestring(pair[i].value)) { if (cbor_isa_bytestring(pair[i].value)) {
str = cbor_bytestring_handle(pair[i].value);
if (!str) {
goto cleanup;
}
nsm_req->data_len = cbor_bytestring_length(pair[i].value);
} else if (cbor_isa_string(pair[i].value)) {
str = cbor_string_handle(pair[i].value);
if (!str) {
goto cleanup;
}
nsm_req->data_len = cbor_string_length(pair[i].value);
} else {
goto cleanup; goto cleanup;
} }
str = cbor_bytestring_handle(pair[i].value);
if (!str) {
goto cleanup;
}
nsm_req->data_len = cbor_bytestring_length(pair[i].value);
/* /*
* nsm_req->data_len will be smaller than NSM_REQUEST_MAX_SIZE as * nsm_req->data_len will be smaller than NSM_REQUEST_MAX_SIZE as
* we already check for the max request size before processing * we already check for the max request size before processing

View file

@ -2,6 +2,7 @@
#define HW_XTENSA_BOOTPARAM_H #define HW_XTENSA_BOOTPARAM_H
#include "exec/cpu-common.h" #include "exec/cpu-common.h"
#include "exec/tswap.h"
#define BP_TAG_COMMAND_LINE 0x1001 /* command line (0-terminated string)*/ #define BP_TAG_COMMAND_LINE 0x1001 /* command line (0-terminated string)*/
#define BP_TAG_INITRD 0x1002 /* ramdisk addr and size (bp_meminfo) */ #define BP_TAG_INITRD 0x1002 /* ramdisk addr and size (bp_meminfo) */

View file

@ -35,6 +35,7 @@
#include "hw/qdev-properties.h" #include "hw/qdev-properties.h"
#include "elf.h" #include "elf.h"
#include "exec/memory.h" #include "exec/memory.h"
#include "exec/tswap.h"
#include "hw/char/serial-mm.h" #include "hw/char/serial-mm.h"
#include "net/net.h" #include "net/net.h"
#include "hw/sysbus.h" #include "hw/sysbus.h"

View file

@ -44,14 +44,14 @@ struct NitroEnclaveMachineState {
/* Machine state */ /* Machine state */
VirtIONSM *vnsm; VirtIONSM *vnsm;
/* kernel + ramdisks + cmdline sha384 hash */ /* kernel + ramdisks + cmdline SHA384 hash */
uint8_t image_sha384[QCRYPTO_HASH_DIGEST_LEN_SHA384]; uint8_t image_hash[QCRYPTO_HASH_DIGEST_LEN_SHA384];
/* kernel + boot ramdisk + cmdline sha384 hash */ /* kernel + boot ramdisk + cmdline SHA384 hash */
uint8_t bootstrap_sha384[QCRYPTO_HASH_DIGEST_LEN_SHA384]; uint8_t bootstrap_hash[QCRYPTO_HASH_DIGEST_LEN_SHA384];
/* application ramdisk(s) hash */ /* application ramdisk(s) SHA384 hash */
uint8_t app_sha384[QCRYPTO_HASH_DIGEST_LEN_SHA384]; uint8_t app_hash[QCRYPTO_HASH_DIGEST_LEN_SHA384];
/* certificate fingerprint hash */ /* certificate fingerprint SHA384 hash */
uint8_t fingerprint_sha384[QCRYPTO_HASH_DIGEST_LEN_SHA384]; uint8_t fingerprint_hash[QCRYPTO_HASH_DIGEST_LEN_SHA384];
bool signature_found; bool signature_found;
}; };

View file

@ -9,6 +9,7 @@
#include "qom/object.h" #include "qom/object.h"
#include "hw/ide/ahci.h" #include "hw/ide/ahci.h"
#include "hw/pci/pci_device.h" #include "hw/pci/pci_device.h"
#include "hw/irq.h"
#define TYPE_ICH9_AHCI "ich9-ahci" #define TYPE_ICH9_AHCI "ich9-ahci"
OBJECT_DECLARE_SIMPLE_TYPE(AHCIPCIState, ICH9_AHCI) OBJECT_DECLARE_SIMPLE_TYPE(AHCIPCIState, ICH9_AHCI)
@ -17,6 +18,7 @@ struct AHCIPCIState {
PCIDevice parent_obj; PCIDevice parent_obj;
AHCIState ahci; AHCIState ahci;
IRQState irq;
}; };
#endif #endif

View file

@ -37,8 +37,6 @@ typedef struct AHCIControlRegs {
} AHCIControlRegs; } AHCIControlRegs;
typedef struct AHCIState { typedef struct AHCIState {
DeviceState *container;
AHCIDevice *dev; AHCIDevice *dev;
AHCIControlRegs control_regs; AHCIControlRegs control_regs;
MemoryRegion mem; MemoryRegion mem;

View file

@ -30,8 +30,9 @@ struct FWCfgDataGeneratorClass {
* @obj: the object implementing this interface * @obj: the object implementing this interface
* @errp: pointer to a NULL-initialized error object * @errp: pointer to a NULL-initialized error object
* *
* Returns: reference to a byte array containing the data on success, * Returns: A byte array containing data to add, or NULL without
* or NULL on error. * @errp set if no data is required, or NULL with @errp
* set on failure.
* *
* The caller should release the reference when no longer * The caller should release the reference when no longer
* required. * required.
@ -291,33 +292,28 @@ void *fw_cfg_modify_file(FWCfgState *s, const char *filename, void *data,
size_t len); size_t len);
/** /**
* fw_cfg_add_from_generator: * fw_cfg_add_file_from_generator:
* @s: fw_cfg device being modified * @s: fw_cfg device being modified
* @filename: name of new fw_cfg file item * @filename: name of new fw_cfg file item
* @gen_id: name of object implementing FW_CFG_DATA_GENERATOR interface * @part: name of object implementing FW_CFG_DATA_GENERATOR interface
* @parent: the object in which to resolve the @part
* @errp: pointer to a NULL initialized error object * @errp: pointer to a NULL initialized error object
* *
* Add a new NAMED fw_cfg item with the content generated from the * If the @part object generates content, add a new NAMED fw_cfg item with it.
* @gen_id object. The data generated by the @gen_id object is copied * The data generated by the @part object is copied into the data structure of
* into the data structure of the fw_cfg device. * the fw_cfg device.
* The next available (unused) selector key starting at FW_CFG_FILE_FIRST * The next available (unused) selector key starting at FW_CFG_FILE_FIRST
* will be used; also, a new entry will be added to the file directory * will be used; also, a new entry will be added to the file directory
* structure residing at key value FW_CFG_FILE_DIR, containing the item name, * structure residing at key value FW_CFG_FILE_DIR, containing the item name,
* data size, and assigned selector key value. * data size, and assigned selector key value.
* *
* If the @part object does not generate content, no fw_cfg item is added.
*
* Returns: %true on success, %false on error. * Returns: %true on success, %false on error.
*/ */
bool fw_cfg_add_from_generator(FWCfgState *s, const char *filename, bool fw_cfg_add_file_from_generator(FWCfgState *s,
const char *gen_id, Error **errp); Object *parent, const char *part,
const char *filename, Error **errp);
/**
* fw_cfg_add_extra_pci_roots:
* @bus: main pci root bus to be scanned from
* @s: fw_cfg device being modified
*
* Add a new fw_cfg item...
*/
void fw_cfg_add_extra_pci_roots(PCIBus *bus, FWCfgState *s);
FWCfgState *fw_cfg_init_io_dma(uint32_t iobase, uint32_t dma_iobase, FWCfgState *fw_cfg_init_io_dma(uint32_t iobase, uint32_t dma_iobase,
AddressSpace *dma_as); AddressSpace *dma_as);

View file

@ -297,6 +297,9 @@ int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
uint32_t pci_bus_get_slot_reserved_mask(PCIBus *bus); uint32_t pci_bus_get_slot_reserved_mask(PCIBus *bus);
void pci_bus_set_slot_reserved_mask(PCIBus *bus, uint32_t mask); void pci_bus_set_slot_reserved_mask(PCIBus *bus, uint32_t mask);
void pci_bus_clear_slot_reserved_mask(PCIBus *bus, uint32_t mask); void pci_bus_clear_slot_reserved_mask(PCIBus *bus, uint32_t mask);
bool pci_bus_add_fw_cfg_extra_pci_roots(FWCfgState *fw_cfg,
PCIBus *bus,
Error **errp);
/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */ /* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
static inline int pci_swizzle(int slot, int pin) static inline int pci_swizzle(int slot, int pin)
{ {

View file

@ -1184,7 +1184,8 @@ static int parse_fw_cfg(void *opaque, QemuOpts *opts, Error **errp)
size = strlen(str); /* NUL terminator NOT included in fw_cfg blob */ size = strlen(str); /* NUL terminator NOT included in fw_cfg blob */
buf = g_memdup(str, size); buf = g_memdup(str, size);
} else if (nonempty_str(gen_id)) { } else if (nonempty_str(gen_id)) {
if (!fw_cfg_add_from_generator(fw_cfg, name, gen_id, errp)) { if (!fw_cfg_add_file_from_generator(fw_cfg, object_get_objects_root(),
gen_id, name, errp)) {
return -1; return -1;
} }
return 0; return 0;