@@ -840,7 +840,7 @@ struct acpi_table_header
} __attribute__((packed));
char *acpi_tables;
-size_t acpi_tables_len;
+size_t acpi_tables_len, acpi_tables_prev_len;
static int acpi_checksum(const uint8_t *data, int len)
{
@@ -851,13 +851,44 @@ static int acpi_checksum(const uint8_t *data, int len)
return (-sum) & 0xff;
}
-int acpi_table_add(const char *t)
+void *acpi_alloc_table(size_t size)
+{
+ void *ptr;
+
+ if (!acpi_tables) {
+ acpi_tables_len = sizeof(uint16_t);
+ acpi_tables = qemu_mallocz(acpi_tables_len);
+ }
+ acpi_tables_prev_len = acpi_tables_len;
+ acpi_tables_len += sizeof(uint16_t) + size;
+ acpi_tables = qemu_realloc(acpi_tables, acpi_tables_len);
+ ptr = acpi_tables + acpi_tables_prev_len;
+
+ *(uint16_t *) ptr = size;
+
+ return ptr + sizeof(uint16_t);
+}
+
+void acpi_commit_table(void *buf)
+{
+ struct acpi_table_header *acpi_hdr = buf;
+ size_t size = acpi_tables_len - acpi_tables_prev_len - sizeof(uint16_t);
+
+ acpi_hdr->length = cpu_to_le32(size);
+ acpi_hdr->checksum = acpi_checksum(buf, size);
+
+ /* increase number of tables */
+ (*(uint16_t *) acpi_tables) =
+ cpu_to_le32(le32_to_cpu(*(uint16_t *) acpi_tables) + 1);
+}
+
+int acpi_table_cmdline_add(const char *t)
{
static const char *dfl_id = "QEMUQEMU";
char buf[1024], *p, *f;
struct acpi_table_header acpi_hdr;
unsigned long val;
- size_t newlen, off;
+ size_t size, off;
memset(&acpi_hdr, 0, sizeof(acpi_hdr));
@@ -915,7 +946,7 @@ int acpi_table_add(const char *t)
buf[0] = '\0';
}
- acpi_hdr.length = sizeof(acpi_hdr);
+ size = sizeof(acpi_hdr);
f = buf;
while (buf[0]) {
@@ -927,27 +958,17 @@ int acpi_table_add(const char *t)
fprintf(stderr, "Can't stat file '%s': %s\n", f, strerror(errno));
goto out;
}
- acpi_hdr.length += s.st_size;
+ size += s.st_size;
if (!n)
break;
*n = ':';
f = n + 1;
}
- if (!acpi_tables) {
- acpi_tables_len = sizeof(uint16_t);
- acpi_tables = qemu_mallocz(acpi_tables_len);
- }
- newlen = acpi_tables_len + sizeof(uint16_t) + acpi_hdr.length;
- acpi_tables = qemu_realloc(acpi_tables, newlen);
- p = acpi_tables + acpi_tables_len;
- acpi_tables_len = newlen;
+ p = acpi_alloc_table(size);
+ off = sizeof(struct acpi_table_header);
- acpi_hdr.length = cpu_to_le32(acpi_hdr.length);
- *(uint16_t*)p = acpi_hdr.length;
- p += sizeof(uint16_t);
- memcpy(p, &acpi_hdr, sizeof(acpi_hdr));
- off = sizeof(acpi_hdr);
+ memcpy(p, &acpi_hdr, off);
f = buf;
while (buf[0]) {
@@ -983,10 +1004,8 @@ int acpi_table_add(const char *t)
f = n + 1;
}
- ((struct acpi_table_header*)p)->checksum = acpi_checksum((uint8_t*)p, off);
- /* increase number of tables */
- (*(uint16_t*)acpi_tables) =
- cpu_to_le32(le32_to_cpu(*(uint16_t*)acpi_tables) + 1);
+ acpi_commit_table(p);
+
return 0;
out:
if (acpi_tables) {
@@ -995,3 +1014,4 @@ out:
}
return -1;
}
+
@@ -108,7 +108,9 @@ extern char *acpi_tables;
extern size_t acpi_tables_len;
void acpi_bios_init(void);
-int acpi_table_add(const char *table_desc);
+void *acpi_alloc_table(size_t size);
+void acpi_commit_table(void *buf);
+int acpi_table_cmdline_add(const char *table_desc);
/* acpi_piix.c */
i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
@@ -5492,7 +5492,7 @@ int main(int argc, char **argv, char **envp)
rtc_td_hack = 1;
break;
case QEMU_OPTION_acpitable:
- if(acpi_table_add(optarg) < 0) {
+ if(acpi_table_cmdline_add(optarg) < 0) {
fprintf(stderr, "Wrong acpi table provided\n");
exit(1);
}
We'd like to let emulation code build and insert ACPI tables at bootup, without depending on hacking the BIOS code. This will be used to provide an IVRS table for emulating the AMD IOMMU, for instance. This splits acpi_table_add(), retaining the old behavior of inserting cmdline-supplied tables under the name of acpi_table_cmdline_add(). The other two resulting functions can be used for the aforementioned purpose. Signed-off-by: Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro> --- hw/acpi.c | 64 ++++++++++++++++++++++++++++++++++++++++--------------------- hw/pc.h | 4 ++- vl.c | 2 +- 3 files changed, 46 insertions(+), 24 deletions(-)