Commit 8a92ea2f2c7b3e185ef6f4d8d3c376b752275ec7

Authored by aliguori
1 parent 680c3069

Allow additions of ACPI tables from command line (Gleb Natapov)

This is needed to dynamically add SLIC tables with Windows
activation keys.
    
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6650 c046a42c-6fe2-441c-8c8c-71466251a162
hw/acpi.c
... ... @@ -746,3 +746,172 @@ void qemu_system_device_hot_add(int bus, int slot, int state)
746 746 qemu_set_irq(pm_state->irq, 0);
747 747 }
748 748 }
  749 +
  750 +struct acpi_table_header
  751 +{
  752 + char signature [4]; /* ACPI signature (4 ASCII characters) */
  753 + uint32_t length; /* Length of table, in bytes, including header */
  754 + uint8_t revision; /* ACPI Specification minor version # */
  755 + uint8_t checksum; /* To make sum of entire table == 0 */
  756 + char oem_id [6]; /* OEM identification */
  757 + char oem_table_id [8]; /* OEM table identification */
  758 + uint32_t oem_revision; /* OEM revision number */
  759 + char asl_compiler_id [4]; /* ASL compiler vendor ID */
  760 + uint32_t asl_compiler_revision; /* ASL compiler revision number */
  761 +} __attribute__((packed));
  762 +
  763 +char *acpi_tables;
  764 +size_t acpi_tables_len;
  765 +
  766 +static int acpi_checksum(const uint8_t *data, int len)
  767 +{
  768 + int sum, i;
  769 + sum = 0;
  770 + for(i = 0; i < len; i++)
  771 + sum += data[i];
  772 + return (-sum) & 0xff;
  773 +}
  774 +
  775 +int acpi_table_add(const char *t)
  776 +{
  777 + static const char *dfl_id = "QEMUQEMU";
  778 + char buf[1024], *p, *f;
  779 + struct acpi_table_header acpi_hdr;
  780 + unsigned long val;
  781 + size_t off;
  782 +
  783 + memset(&acpi_hdr, 0, sizeof(acpi_hdr));
  784 +
  785 + if (get_param_value(buf, sizeof(buf), "sig", t)) {
  786 + strncpy(acpi_hdr.signature, buf, 4);
  787 + } else {
  788 + strncpy(acpi_hdr.signature, dfl_id, 4);
  789 + }
  790 + if (get_param_value(buf, sizeof(buf), "rev", t)) {
  791 + val = strtoul(buf, &p, 10);
  792 + if (val > 255 || *p != '\0')
  793 + goto out;
  794 + } else {
  795 + val = 1;
  796 + }
  797 + acpi_hdr.revision = (int8_t)val;
  798 +
  799 + if (get_param_value(buf, sizeof(buf), "oem_id", t)) {
  800 + strncpy(acpi_hdr.oem_id, buf, 6);
  801 + } else {
  802 + strncpy(acpi_hdr.oem_id, dfl_id, 6);
  803 + }
  804 +
  805 + if (get_param_value(buf, sizeof(buf), "oem_table_id", t)) {
  806 + strncpy(acpi_hdr.oem_table_id, buf, 8);
  807 + } else {
  808 + strncpy(acpi_hdr.oem_table_id, dfl_id, 8);
  809 + }
  810 +
  811 + if (get_param_value(buf, sizeof(buf), "oem_rev", t)) {
  812 + val = strtol(buf, &p, 10);
  813 + if(*p != '\0')
  814 + goto out;
  815 + } else {
  816 + val = 1;
  817 + }
  818 + acpi_hdr.oem_revision = cpu_to_le32(val);
  819 +
  820 + if (get_param_value(buf, sizeof(buf), "asl_compiler_id", t)) {
  821 + strncpy(acpi_hdr.asl_compiler_id, buf, 4);
  822 + } else {
  823 + strncpy(acpi_hdr.asl_compiler_id, dfl_id, 4);
  824 + }
  825 +
  826 + if (get_param_value(buf, sizeof(buf), "asl_compiler_rev", t)) {
  827 + val = strtol(buf, &p, 10);
  828 + if(*p != '\0')
  829 + goto out;
  830 + } else {
  831 + val = 1;
  832 + }
  833 + acpi_hdr.asl_compiler_revision = cpu_to_le32(val);
  834 +
  835 + if (!get_param_value(buf, sizeof(buf), "data", t)) {
  836 + buf[0] = '\0';
  837 + }
  838 +
  839 + acpi_hdr.length = sizeof(acpi_hdr);
  840 +
  841 + f = buf;
  842 + while (buf[0]) {
  843 + struct stat s;
  844 + char *n = index(f, ':');
  845 + if (n)
  846 + *n = '\0';
  847 + if(stat(f, &s) < 0) {
  848 + fprintf(stderr, "Can't stat file '%s': %s\n", f, strerror(errno));
  849 + goto out;
  850 + }
  851 + acpi_hdr.length += s.st_size;
  852 + if (!n)
  853 + break;
  854 + *n = ':';
  855 + f = n + 1;
  856 + }
  857 +
  858 + if (!acpi_tables) {
  859 + acpi_tables_len = sizeof(uint16_t);
  860 + acpi_tables = qemu_mallocz(acpi_tables_len);
  861 + }
  862 + p = acpi_tables + acpi_tables_len;
  863 + acpi_tables_len += sizeof(uint16_t) + acpi_hdr.length;
  864 + acpi_tables = qemu_realloc(acpi_tables, acpi_tables_len);
  865 +
  866 + acpi_hdr.length = cpu_to_le32(acpi_hdr.length);
  867 + *(uint16_t*)p = acpi_hdr.length;
  868 + p += sizeof(uint16_t);
  869 + memcpy(p, &acpi_hdr, sizeof(acpi_hdr));
  870 + off = sizeof(acpi_hdr);
  871 +
  872 + f = buf;
  873 + while (buf[0]) {
  874 + struct stat s;
  875 + int fd;
  876 + char *n = index(f, ':');
  877 + if (n)
  878 + *n = '\0';
  879 + fd = open(f, O_RDONLY);
  880 +
  881 + if(fd < 0)
  882 + goto out;
  883 + if(fstat(fd, &s) < 0) {
  884 + close(fd);
  885 + goto out;
  886 + }
  887 +
  888 + do {
  889 + int r;
  890 + r = read(fd, p + off, s.st_size);
  891 + if (r > 0) {
  892 + off += r;
  893 + s.st_size -= r;
  894 + } else if ((r < 0 && errno != EINTR) || r == 0) {
  895 + close(fd);
  896 + goto out;
  897 + }
  898 + } while(s.st_size);
  899 +
  900 + close(fd);
  901 + if (!n)
  902 + break;
  903 + f = n + 1;
  904 + }
  905 +
  906 + ((struct acpi_table_header*)p)->checksum = acpi_checksum((uint8_t*)p, off);
  907 + /* increase number of tables */
  908 + (*(uint16_t*)acpi_tables) =
  909 + cpu_to_le32(le32_to_cpu(*(uint16_t*)acpi_tables) + 1);
  910 + return 0;
  911 +out:
  912 + if (acpi_tables) {
  913 + free(acpi_tables);
  914 + acpi_tables = NULL;
  915 + }
  916 + return -1;
  917 +}
... ...
... ... @@ -50,9 +50,13 @@
50 50 /* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables. */
51 51 #define ACPI_DATA_SIZE 0x10000
52 52 #define BIOS_CFG_IOPORT 0x510
  53 +#define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0)
53 54  
54 55 #define MAX_IDE_BUS 2
55 56  
  57 +extern uint8_t *acpi_tables;
  58 +extern size_t acpi_tables_len;
  59 +
56 60 static fdctrl_t *floppy_controller;
57 61 static RTCState *rtc_state;
58 62 static PITState *pit;
... ... @@ -438,6 +442,7 @@ static void bochs_bios_init(void)
438 442 fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
439 443 fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
440 444 fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
  445 + fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES, acpi_tables, acpi_tables_len);
441 446 }
442 447  
443 448 /* Generate an initial boot sector which sets state and jump to
... ...
... ... @@ -102,6 +102,7 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
102 102 qemu_irq sci_irq);
103 103 void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);
104 104 void acpi_bios_init(void);
  105 +int acpi_table_add(const char *table_desc);
105 106  
106 107 /* hpet.c */
107 108 extern int no_hpet;
... ...
pc-bios/bios-pq/0011_read-additional-acpi-tables-from-a-vm.patch 0 โ†’ 100644
  1 +Read additional ACPI tables from a VM (Gleb Natapov)
  2 +
  3 +Signed-off-by: Gleb Natapov <gleb@redhat.com>
  4 +Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
  5 +
  6 +diff --git a/bios/rombios32.c b/bios/rombios32.c
  7 +index 3269be5..191707d 100644
  8 +--- a/bios/rombios32.c
  9 ++++ b/bios/rombios32.c
  10 +@@ -457,6 +457,8 @@ void wrmsr_smp(uint32_t index, uint64_t val)
  11 + #define QEMU_CFG_SIGNATURE 0x00
  12 + #define QEMU_CFG_ID 0x01
  13 + #define QEMU_CFG_UUID 0x02
  14 ++#define QEMU_CFG_ARCH_LOCAL 0x8000
  15 ++#define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0)
  16 +
  17 + int qemu_cfg_port;
  18 +
  19 +@@ -484,6 +486,27 @@ void qemu_cfg_read(uint8_t *buf, int len)
  20 + while (len--)
  21 + *(buf++) = inb(QEMU_CFG_DATA_PORT);
  22 + }
  23 ++
  24 ++static uint16_t acpi_additional_tables(void)
  25 ++{
  26 ++ uint16_t cnt;
  27 ++
  28 ++ qemu_cfg_select(QEMU_CFG_ACPI_TABLES);
  29 ++ qemu_cfg_read((uint8_t*)&cnt, sizeof(cnt));
  30 ++
  31 ++ return cnt;
  32 ++}
  33 ++
  34 ++static int acpi_load_table(int i, uint32_t addr, uint16_t *len)
  35 ++{
  36 ++ qemu_cfg_read((uint8_t*)len, sizeof(*len));
  37 ++
  38 ++ if (!*len)
  39 ++ return -1;
  40 ++
  41 ++ qemu_cfg_read((uint8_t*)addr, *len);
  42 ++ return 0;
  43 ++}
  44 + #endif
  45 +
  46 + void uuid_probe(void)
  47 +@@ -1534,8 +1557,8 @@ void acpi_bios_init(void)
  48 + uint32_t hpet_addr;
  49 + #endif
  50 + uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr, ssdt_addr;
  51 +- uint32_t acpi_tables_size, madt_addr, madt_size;
  52 +- int i;
  53 ++ uint32_t acpi_tables_size, madt_addr, madt_size, rsdt_size;
  54 ++ uint16_t i, external_tables;
  55 +
  56 + /* reserve memory space for tables */
  57 + #ifdef BX_USE_EBDA_TABLES
  58 +@@ -1548,10 +1571,17 @@ void acpi_bios_init(void)
  59 + bios_table_cur_addr += sizeof(*rsdp);
  60 + #endif
  61 +
  62 ++#ifdef BX_QEMU
  63 ++ external_tables = acpi_additional_tables();
  64 ++#else
  65 ++ external_tables = 0;
  66 ++#endif
  67 ++
  68 + addr = base_addr = ram_size - ACPI_DATA_SIZE;
  69 + rsdt_addr = addr;
  70 + rsdt = (void *)(addr);
  71 +- addr += sizeof(*rsdt);
  72 ++ rsdt_size = sizeof(*rsdt) + external_tables * 4;
  73 ++ addr += rsdt_size;
  74 +
  75 + fadt_addr = addr;
  76 + fadt = (void *)(addr);
  77 +@@ -1590,12 +1620,6 @@ void acpi_bios_init(void)
  78 + addr += sizeof(*hpet);
  79 + #endif
  80 +
  81 +- acpi_tables_size = addr - base_addr;
  82 +-
  83 +- BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n",
  84 +- (unsigned long)rsdp,
  85 +- (unsigned long)rsdt, acpi_tables_size);
  86 +-
  87 + /* RSDP */
  88 + memset(rsdp, 0, sizeof(*rsdp));
  89 + memcpy(rsdp->signature, "RSD PTR ", 8);
  90 +@@ -1607,17 +1631,6 @@ void acpi_bios_init(void)
  91 + rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr);
  92 + rsdp->checksum = acpi_checksum((void *)rsdp, 20);
  93 +
  94 +- /* RSDT */
  95 +- memset(rsdt, 0, sizeof(*rsdt));
  96 +- rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr);
  97 +- rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr);
  98 +- rsdt->table_offset_entry[2] = cpu_to_le32(ssdt_addr);
  99 +-#ifdef BX_QEMU
  100 +- rsdt->table_offset_entry[3] = cpu_to_le32(hpet_addr);
  101 +-#endif
  102 +- acpi_build_table_header((struct acpi_table_header *)rsdt,
  103 +- "RSDT", sizeof(*rsdt), 1);
  104 +-
  105 + /* FADT */
  106 + memset(fadt, 0, sizeof(*fadt));
  107 + fadt->firmware_ctrl = cpu_to_le32(facs_addr);
  108 +@@ -1692,6 +1705,7 @@ void acpi_bios_init(void)
  109 + "APIC", madt_size, 1);
  110 + }
  111 +
  112 ++ memset(rsdt, 0, rsdt_size);
  113 + #ifdef BX_QEMU
  114 + /* HPET */
  115 + memset(hpet, 0, sizeof(*hpet));
  116 +@@ -1702,7 +1716,34 @@ void acpi_bios_init(void)
  117 + hpet->addr.address = cpu_to_le32(ACPI_HPET_ADDRESS);
  118 + acpi_build_table_header((struct acpi_table_header *)hpet,
  119 + "HPET", sizeof(*hpet), 1);
  120 ++
  121 ++ acpi_additional_tables(); /* resets cfg to required entry */
  122 ++ for(i = 0; i < external_tables; i++) {
  123 ++ uint16_t len;
  124 ++ if(acpi_load_table(i, addr, &len) < 0)
  125 ++ BX_PANIC("Failed to load ACPI table from QEMU\n");
  126 ++ rsdt->table_offset_entry[i+4] = cpu_to_le32(addr);
  127 ++ addr += len;
  128 ++ if(addr >= ram_size)
  129 ++ BX_PANIC("ACPI table overflow\n");
  130 ++ }
  131 ++#endif
  132 ++
  133 ++ /* RSDT */
  134 ++ rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr);
  135 ++ rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr);
  136 ++ rsdt->table_offset_entry[2] = cpu_to_le32(ssdt_addr);
  137 ++#ifdef BX_QEMU
  138 ++ rsdt->table_offset_entry[3] = cpu_to_le32(hpet_addr);
  139 + #endif
  140 ++ acpi_build_table_header((struct acpi_table_header *)rsdt,
  141 ++ "RSDT", rsdt_size, 1);
  142 ++
  143 ++ acpi_tables_size = addr - base_addr;
  144 ++
  145 ++ BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n",
  146 ++ (unsigned long)rsdp,
  147 ++ (unsigned long)rsdt, acpi_tables_size);
  148 +
  149 + }
  150 +
  151 +--
  152 + Gleb.
  153 +
  154 +
  155 +
... ...
pc-bios/bios-pq/series
... ... @@ -8,3 +8,4 @@
8 8 0008_qemu-bios-provide-gpe-_l0x-methods.patch
9 9 0009_qemu-bios-pci-hotplug-support.patch
10 10 0010_bios-mark-the-acpi-sci-interrupt-as-connected-to-irq-9.patch
  11 +0011_read-additional-acpi-tables-from-a-vm.patch
... ...
pc-bios/bios.bin
No preview for this file type
qemu-doc.texi
... ... @@ -896,6 +896,9 @@ only).
896 896 @item -no-hpet
897 897 Disable HPET support.
898 898  
  899 +@item -acpitable [sig=@var{str}][,rev=@var{n}][,oem_id=@var{str}][,oem_table_id=@var{str}][,oem_rev=@var{n}] [,asl_compiler_id=@var{str}][,asl_compiler_rev=@var{n}][,data=@var{file1}[:@var{file2}]...]
  900 +Add ACPI table with specified header fields and context from specified files.
  901 +
899 902 @end table
900 903  
901 904 Linux boot specific: When using these options, you can use a given
... ...
... ... @@ -4016,6 +4016,8 @@ static void help(int exitcode)
4016 4016 "-no-fd-bootchk disable boot signature checking for floppy disks\n"
4017 4017 "-no-acpi disable ACPI\n"
4018 4018 "-no-hpet disable HPET\n"
  4019 + "-acpitable [sig=str][,rev=n][,oem_id=str][,oem_table_id=str][,oem_rev=n][,asl_compiler_id=str][,asl_compiler_rev=n][,data=file1[:file2]...]\n"
  4020 + " ACPI table description\n"
4019 4021 #endif
4020 4022 "Linux boot specific:\n"
4021 4023 "-kernel bzImage use 'bzImage' as kernel image\n"
... ... @@ -4151,6 +4153,7 @@ enum {
4151 4153 QEMU_OPTION_no_fd_bootchk,
4152 4154 QEMU_OPTION_no_acpi,
4153 4155 QEMU_OPTION_no_hpet,
  4156 + QEMU_OPTION_acpitable,
4154 4157  
4155 4158 /* Linux boot specific: */
4156 4159 QEMU_OPTION_kernel,
... ... @@ -4269,6 +4272,7 @@ static const QEMUOption qemu_options[] = {
4269 4272 { "no-fd-bootchk", 0, QEMU_OPTION_no_fd_bootchk },
4270 4273 { "no-acpi", 0, QEMU_OPTION_no_acpi },
4271 4274 { "no-hpet", 0, QEMU_OPTION_no_hpet },
  4275 + { "acpitable", HAS_ARG, QEMU_OPTION_acpitable },
4272 4276 #endif
4273 4277  
4274 4278 /* Linux boot specific: */
... ... @@ -5127,6 +5131,12 @@ int main(int argc, char **argv, char **envp)
5127 5131 case QEMU_OPTION_rtc_td_hack:
5128 5132 rtc_td_hack = 1;
5129 5133 break;
  5134 + case QEMU_OPTION_acpitable:
  5135 + if(acpi_table_add(optarg) < 0) {
  5136 + fprintf(stderr, "Wrong acpi table provided\n");
  5137 + exit(1);
  5138 + }
  5139 + break;
5130 5140 #endif
5131 5141 #ifdef USE_KQEMU
5132 5142 case QEMU_OPTION_no_kqemu:
... ...