From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:36788) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QWuhP-0007Vi-KE for qemu-devel@nongnu.org; Wed, 15 Jun 2011 14:20:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QWuhN-0004sn-EY for qemu-devel@nongnu.org; Wed, 15 Jun 2011 14:20:19 -0400 Received: from mail-qw0-f45.google.com ([209.85.216.45]:42698) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QWuhM-0004sj-VH for qemu-devel@nongnu.org; Wed, 15 Jun 2011 14:20:17 -0400 Received: by qwj8 with SMTP id 8so396579qwj.4 for ; Wed, 15 Jun 2011 11:20:16 -0700 (PDT) MIME-Version: 1.0 In-Reply-To: <4DF29AD2.2@msgid.tls.msk.ru> References: <20110606083447.47A88527A@gandalf.tls.msk.ru> <4DF29AD2.2@msgid.tls.msk.ru> From: Blue Swirl Date: Wed, 15 Jun 2011 21:19:56 +0300 Message-ID: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH] v6 revamp acpitable parsing and allow to specify complete (headerful) table List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Michael Tokarev Cc: Isaku Yamahata , qemu-devel@nongnu.org, Anthony Liguori On Sat, Jun 11, 2011 at 1:29 AM, Michael Tokarev wrote: > I've given up on this one. =C2=A0Personally I don't need > this stuff for my win7 guests since I can hack either > bios or the O/S loader to include all the necessary > verifications for the win7 activation to work. =C2=A0I > tried to make this process to be legal (no hacks > or "cracks" needed) and easy for others, but since > noone is interested in this after 6 versions and 5 > resends, I wont continue - what I am trying to achieve > by pushing this so hard, after all? > > Thanks to everyone who gave (mostly code style) comments - > at least I know the changes has been read by someone. > > Frustrated, Sorry about that. I get this error: /src/qemu/hw/acpi.c: In function 'acpi_table_add': /src/qemu/hw/acpi.c:167: error: format '%u' expects type 'unsigned int', but argument 4 has type 'size_t' > =C2=A0/mjt > > 12.05.2011 18:44, Michael Tokarev wrote: >> This patch almost rewrites acpi_table_add() function >> (but still leaves it using old get_param_value() interface). >> The result is that it's now possible to specify whole table >> (together with a header) in an external file, instead of just >> data portion, with a new file=3D parameter, but at the same time >> it's still possible to specify header fields as before. >> >> Now with the checkpatch.pl formatting fixes, thanks to >> Stefan Hajnoczi for suggestions, with changes from >> Isaku Yamahata, and with my further refinements. >> >> v5: rediffed against current qemu/master. >> v6: fix one "} else {" coding style defect (noted by Blue Swirl) >> >> Signed-off-by: Michael Tokarev >> --- >> =C2=A0hw/acpi.c =C2=A0 =C2=A0 =C2=A0 | =C2=A0292 +++++++++++++++++++++++= +++++++++----------------------- >> =C2=A0qemu-options.hx | =C2=A0 =C2=A07 +- >> =C2=A02 files changed, 175 insertions(+), 124 deletions(-) >> >> diff --git a/hw/acpi.c b/hw/acpi.c >> index ad40fb4..4316189 100644 >> --- a/hw/acpi.c >> +++ b/hw/acpi.c >> @@ -22,17 +22,29 @@ >> >> =C2=A0struct acpi_table_header >> =C2=A0{ >> - =C2=A0 =C2=A0char signature [4]; =C2=A0 =C2=A0/* ACPI signature (4 ASC= II characters) */ >> + =C2=A0 =C2=A0uint16_t _length; =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* our leng= th, not actual part of the hdr */ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* XXX why we have 2 length fields here? = */ >> + =C2=A0 =C2=A0char sig[4]; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0/* ACPI signature (4 ASCII characters) */ >> =C2=A0 =C2=A0 =C2=A0uint32_t length; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/= * Length of table, in bytes, including header */ >> =C2=A0 =C2=A0 =C2=A0uint8_t revision; =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* ACP= I Specification minor version # */ >> =C2=A0 =C2=A0 =C2=A0uint8_t checksum; =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* To = make sum of entire table =3D=3D 0 */ >> - =C2=A0 =C2=A0char oem_id [6]; =C2=A0 =C2=A0 =C2=A0 /* OEM identificati= on */ >> - =C2=A0 =C2=A0char oem_table_id [8]; /* OEM table identification */ >> + =C2=A0 =C2=A0char oem_id[6]; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* OEM= identification */ >> + =C2=A0 =C2=A0char oem_table_id[8]; =C2=A0 =C2=A0 /* OEM table identifi= cation */ >> =C2=A0 =C2=A0 =C2=A0uint32_t oem_revision; =C2=A0 =C2=A0/* OEM revision = number */ >> - =C2=A0 =C2=A0char asl_compiler_id [4]; /* ASL compiler vendor ID */ >> + =C2=A0 =C2=A0char asl_compiler_id[4]; =C2=A0/* ASL compiler vendor ID = */ >> =C2=A0 =C2=A0 =C2=A0uint32_t asl_compiler_revision; /* ASL compiler revi= sion number */ >> =C2=A0} __attribute__((packed)); >> >> +#define ACPI_TABLE_HDR_SIZE sizeof(struct acpi_table_header) >> +#define ACPI_TABLE_PFX_SIZE sizeof(uint16_t) =C2=A0/* size of the extra= prefix */ >> + >> +static const char dfl_hdr[ACPI_TABLE_HDR_SIZE] =3D >> + =C2=A0 =C2=A0"\0\0" =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 /* fake _length (2) */ >> + =C2=A0 =C2=A0"QEMU\0\0\0\0\1\0" =C2=A0 =C2=A0 =C2=A0 /* sig (4), len(4= ), revno (1), csum (1) */ >> + =C2=A0 =C2=A0"QEMUQEQEMUQEMU\1\0\0\0" /* OEM id (6), table (8), revno = (4) */ >> + =C2=A0 =C2=A0"QEMU\1\0\0\0" =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* ASL = compiler ID (4), version (4) */ >> + =C2=A0 =C2=A0; >> + >> =C2=A0char *acpi_tables; >> =C2=A0size_t acpi_tables_len; >> >> @@ -45,158 +57,192 @@ static int acpi_checksum(const uint8_t *data, int = len) >> =C2=A0 =C2=A0 =C2=A0return (-sum) & 0xff; >> =C2=A0} >> >> +/* like strncpy() but zero-fills the tail of destination */ >> +static void strzcpy(char *dst, const char *src, size_t size) >> +{ >> + =C2=A0 =C2=A0size_t len =3D strlen(src); >> + =C2=A0 =C2=A0if (len >=3D size) { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0len =3D size; >> + =C2=A0 =C2=A0} else { >> + =C2=A0 =C2=A0 =C2=A0memset(dst + len, 0, size - len); >> + =C2=A0 =C2=A0} >> + =C2=A0 =C2=A0memcpy(dst, src, len); >> +} >> + >> +/* XXX fixme: this function uses obsolete argument parsing interface */ >> =C2=A0int acpi_table_add(const char *t) >> =C2=A0{ >> - =C2=A0 =C2=A0static const char *dfl_id =3D "QEMUQEMU"; >> =C2=A0 =C2=A0 =C2=A0char buf[1024], *p, *f; >> - =C2=A0 =C2=A0struct acpi_table_header acpi_hdr; >> =C2=A0 =C2=A0 =C2=A0unsigned long val; >> - =C2=A0 =C2=A0uint32_t length; >> - =C2=A0 =C2=A0struct acpi_table_header *acpi_hdr_p; >> - =C2=A0 =C2=A0size_t off; >> + =C2=A0 =C2=A0size_t len, start, allen; >> + =C2=A0 =C2=A0bool has_header; >> + =C2=A0 =C2=A0int changed; >> + =C2=A0 =C2=A0int r; >> + =C2=A0 =C2=A0struct acpi_table_header hdr; >> + >> + =C2=A0 =C2=A0r =3D 0; >> + =C2=A0 =C2=A0r |=3D get_param_value(buf, sizeof(buf), "data", t) ? 1 := 0; >> + =C2=A0 =C2=A0r |=3D get_param_value(buf, sizeof(buf), "file", t) ? 2 := 0; >> + =C2=A0 =C2=A0switch (r) { >> + =C2=A0 =C2=A0case 0: >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0buf[0] =3D '\0'; Missing 'break' or comment about fall through. >> + =C2=A0 =C2=A0case 1: >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0has_header =3D false; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0break; >> + =C2=A0 =C2=A0case 2: >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0has_header =3D true; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0break; >> + =C2=A0 =C2=A0default: >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0fprintf(stderr, "acpitable: both data and f= ile are specified\n"); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0return -1; >> + =C2=A0 =C2=A0} >> + >> + =C2=A0 =C2=A0if (!acpi_tables) { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0allen =3D sizeof(uint16_t); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0acpi_tables =3D qemu_mallocz(allen); >> + =C2=A0 =C2=A0} >> + =C2=A0 =C2=A0else { 'else' belongs to the previous line. >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0allen =3D acpi_tables_len; >> + =C2=A0 =C2=A0} >> + >> + =C2=A0 =C2=A0start =3D allen; >> + =C2=A0 =C2=A0acpi_tables =3D qemu_realloc(acpi_tables, start + ACPI_TA= BLE_HDR_SIZE); >> + =C2=A0 =C2=A0allen +=3D has_header ? ACPI_TABLE_PFX_SIZE : ACPI_TABLE_= HDR_SIZE; >> + >> + =C2=A0 =C2=A0/* now read in the data files, reallocating buffer as nee= ded */ >> + >> + =C2=A0 =C2=A0for (f =3D strtok(buf, ":"); f; f =3D strtok(NULL, ":")) = { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0int fd =3D open(f, O_RDONLY); >> + >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0if (fd < 0) { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fprintf(stderr, "can't open f= ile %s: %s\n", f, strerror(errno)); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return -1; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0} >> + >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0for (;;) { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0char data[8192]; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0r =3D read(fd, data, sizeof(d= ata)); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (r =3D=3D 0) { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0break; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} else if (r > 0) { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0acpi_tables =3D= qemu_realloc(acpi_tables, allen + r); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0memcpy(acpi_tab= les + allen, data, r); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0allen +=3D r; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} else if (errno !=3D EINTR) = { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fprintf(stderr,= "can't read file %s: %s\n", >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0f, strerror(errno)); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0close(fd); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return -1; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0} >> + >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0close(fd); >> + =C2=A0 =C2=A0} >> + >> + =C2=A0 =C2=A0/* now fill in the header fields */ >> + >> + =C2=A0 =C2=A0f =3D acpi_tables + start; =C2=A0 /* start of the table *= / >> + =C2=A0 =C2=A0changed =3D 0; >> + >> + =C2=A0 =C2=A0/* copy the header to temp place to align the fields */ >> + =C2=A0 =C2=A0memcpy(&hdr, has_header ? f : dfl_hdr, ACPI_TABLE_HDR_SIZ= E); >> + >> + =C2=A0 =C2=A0/* length of the table minus our prefix */ >> + =C2=A0 =C2=A0len =3D allen - start - ACPI_TABLE_PFX_SIZE; >> + >> + =C2=A0 =C2=A0hdr._length =3D cpu_to_le16(len); >> >> - =C2=A0 =C2=A0memset(&acpi_hdr, 0, sizeof(acpi_hdr)); >> - >> =C2=A0 =C2=A0 =C2=A0if (get_param_value(buf, sizeof(buf), "sig", t)) { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0strncpy(acpi_hdr.signature, buf, 4); >> - =C2=A0 =C2=A0} else { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0strncpy(acpi_hdr.signature, dfl_id, 4); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0strzcpy(hdr.sig, buf, sizeof(hdr.sig)); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0++changed; >> =C2=A0 =C2=A0 =C2=A0} >> + >> + =C2=A0 =C2=A0/* length of the table including header, in bytes */ >> + =C2=A0 =C2=A0if (has_header) { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0/* check if actual length is correct */ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0val =3D le32_to_cpu(hdr.length); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0if (val !=3D len) { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fprintf(stderr, >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"warning: acpit= able has wrong length," >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0" header says %= lu, actual size %u bytes\n", >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0val, len); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0++changed; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0} >> + =C2=A0 =C2=A0} >> + =C2=A0 =C2=A0/* we may avoid putting length here if has_header is true= */ >> + =C2=A0 =C2=A0hdr.length =3D cpu_to_le32(len); >> + >> =C2=A0 =C2=A0 =C2=A0if (get_param_value(buf, sizeof(buf), "rev", t)) { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0val =3D strtoul(buf, &p, 10); >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0if (val > 255 || *p !=3D '\0') >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto out; >> - =C2=A0 =C2=A0} else { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0val =3D 1; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0val =3D strtoul(buf, &p, 0); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0if (val > 255 || *p) { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fprintf(stderr, "acpitable: \= "rev=3D%s\" is invalid\n", buf); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return -1; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0} >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0hdr.revision =3D (uint8_t)val; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0++changed; >> =C2=A0 =C2=A0 =C2=A0} >> - =C2=A0 =C2=A0acpi_hdr.revision =3D (int8_t)val; >> >> =C2=A0 =C2=A0 =C2=A0if (get_param_value(buf, sizeof(buf), "oem_id", t)) = { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0strncpy(acpi_hdr.oem_id, buf, 6); >> - =C2=A0 =C2=A0} else { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0strncpy(acpi_hdr.oem_id, dfl_id, 6); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0strzcpy(hdr.oem_id, buf, sizeof(hdr.oem_id)= ); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0++changed; >> =C2=A0 =C2=A0 =C2=A0} >> >> =C2=A0 =C2=A0 =C2=A0if (get_param_value(buf, sizeof(buf), "oem_table_id"= , t)) { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0strncpy(acpi_hdr.oem_table_id, buf, 8); >> - =C2=A0 =C2=A0} else { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0strncpy(acpi_hdr.oem_table_id, dfl_id, 8); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0strzcpy(hdr.oem_table_id, buf, sizeof(hdr.o= em_table_id)); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0++changed; >> =C2=A0 =C2=A0 =C2=A0} >> >> =C2=A0 =C2=A0 =C2=A0if (get_param_value(buf, sizeof(buf), "oem_rev", t))= { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0val =3D strtol(buf, &p, 10); >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0if(*p !=3D '\0') >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto out; >> - =C2=A0 =C2=A0} else { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0val =3D 1; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0val =3D strtol(buf, &p, 0); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0if (*p) { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fprintf(stderr, "acpitable: \= "oem_rev=3D%s\" is invalid\n", buf); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return -1; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0} >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0hdr.oem_revision =3D cpu_to_le32(val); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0++changed; >> =C2=A0 =C2=A0 =C2=A0} >> - =C2=A0 =C2=A0acpi_hdr.oem_revision =3D cpu_to_le32(val); >> >> =C2=A0 =C2=A0 =C2=A0if (get_param_value(buf, sizeof(buf), "asl_compiler_= id", t)) { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0strncpy(acpi_hdr.asl_compiler_id, buf, 4); >> - =C2=A0 =C2=A0} else { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0strncpy(acpi_hdr.asl_compiler_id, dfl_id, 4= ); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0strzcpy(hdr.asl_compiler_id, buf, sizeof(hd= r.asl_compiler_id)); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0++changed; >> =C2=A0 =C2=A0 =C2=A0} >> >> =C2=A0 =C2=A0 =C2=A0if (get_param_value(buf, sizeof(buf), "asl_compiler_= rev", t)) { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0val =3D strtol(buf, &p, 10); >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0if(*p !=3D '\0') >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto out; >> - =C2=A0 =C2=A0} else { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0val =3D 1; >> - =C2=A0 =C2=A0} >> - =C2=A0 =C2=A0acpi_hdr.asl_compiler_revision =3D cpu_to_le32(val); >> - >> - =C2=A0 =C2=A0if (!get_param_value(buf, sizeof(buf), "data", t)) { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 buf[0] =3D '\0'; >> - =C2=A0 =C2=A0} >> - >> - =C2=A0 =C2=A0length =3D sizeof(acpi_hdr); >> - >> - =C2=A0 =C2=A0f =3D buf; >> - =C2=A0 =C2=A0while (buf[0]) { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0struct stat s; >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0char *n =3D strchr(f, ':'); >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0if (n) >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*n =3D '\0'; >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0if(stat(f, &s) < 0) { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fprintf(stderr, "Can't stat f= ile '%s': %s\n", f, strerror(errno)); >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto out; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0val =3D strtol(buf, &p, 0); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0if (*p) { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fprintf(stderr, "acpitable: \= "%s=3D%s\" is invalid\n", >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"= asl_compiler_rev", buf); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return -1; >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0length +=3D s.st_size; >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0if (!n) >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0break; >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0*n =3D ':'; >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0f =3D n + 1; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0hdr.asl_compiler_revision =3D cpu_to_le32(v= al); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0++changed; >> =C2=A0 =C2=A0 =C2=A0} >> >> - =C2=A0 =C2=A0if (!acpi_tables) { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0acpi_tables_len =3D sizeof(uint16_t); >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0acpi_tables =3D qemu_mallocz(acpi_tables_le= n); >> + =C2=A0 =C2=A0if (!has_header && !changed) { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0fprintf(stderr, "warning: acpitable: no tab= le headers are specified\n"); >> =C2=A0 =C2=A0 =C2=A0} >> - =C2=A0 =C2=A0acpi_tables =3D qemu_realloc(acpi_tables, >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 acpi_tables_len + sizeof(uint16_t) + len= gth); >> - =C2=A0 =C2=A0p =3D acpi_tables + acpi_tables_len; >> - =C2=A0 =C2=A0acpi_tables_len +=3D sizeof(uint16_t) + length; >> - >> - =C2=A0 =C2=A0*(uint16_t*)p =3D cpu_to_le32(length); >> - =C2=A0 =C2=A0p +=3D sizeof(uint16_t); >> - =C2=A0 =C2=A0memcpy(p, &acpi_hdr, sizeof(acpi_hdr)); >> - =C2=A0 =C2=A0off =3D sizeof(acpi_hdr); >> - >> - =C2=A0 =C2=A0f =3D buf; >> - =C2=A0 =C2=A0while (buf[0]) { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0struct stat s; >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0int fd; >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0char *n =3D strchr(f, ':'); >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0if (n) >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*n =3D '\0'; >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0fd =3D open(f, O_RDONLY); >> - >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0if(fd < 0) >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto out; >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0if(fstat(fd, &s) < 0) { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0close(fd); >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto out; >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0} >> >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0/* off < length is necessary because file s= ize can be changed >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 under our foot */ >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0while(s.st_size && off < length) { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0int r; >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0r =3D read(fd, p + off, s.st_= size); >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (r > 0) { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0off +=3D r; >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0s.st_size -=3D = r; >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} else if ((r < 0 && errno != =3D EINTR) || r =3D=3D 0) { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0close(fd); >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto out; >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0} >> >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0close(fd); >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0if (!n) >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0break; >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0f =3D n + 1; >> - =C2=A0 =C2=A0} >> - =C2=A0 =C2=A0if (off < length) { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0/* don't pass random value in process to gu= est */ >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0memset(p + off, 0, length - off); >> + =C2=A0 =C2=A0/* now calculate checksum of the table, complete with the= header */ >> + =C2=A0 =C2=A0/* we may as well leave checksum intact if has_header is = true */ >> + =C2=A0 =C2=A0/* alternatively there may be a way to set cksum to a giv= en value */ >> + =C2=A0 =C2=A0hdr.checksum =3D 0; =C2=A0 =C2=A0/* for checksum calculat= ion */ >> + >> + =C2=A0 =C2=A0/* put header back */ >> + =C2=A0 =C2=A0memcpy(f, &hdr, sizeof(hdr)); >> + >> + =C2=A0 =C2=A0if (changed || !has_header || 1) { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0((struct acpi_table_header *)f)->checksum = =3D >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0acpi_checksum((uint8_t *)f + = ACPI_TABLE_PFX_SIZE, len); >> =C2=A0 =C2=A0 =C2=A0} >> >> - =C2=A0 =C2=A0acpi_hdr_p =3D (struct acpi_table_header*)p; >> - =C2=A0 =C2=A0acpi_hdr_p->length =3D cpu_to_le32(length); >> - =C2=A0 =C2=A0acpi_hdr_p->checksum =3D acpi_checksum((uint8_t*)p, lengt= h); >> =C2=A0 =C2=A0 =C2=A0/* increase number of tables */ >> - =C2=A0 =C2=A0(*(uint16_t*)acpi_tables) =3D >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpu_to_le32(le32_to_cpu(*(uint16_t*)acpi_t= ables) + 1); >> + =C2=A0 =C2=A0(*(uint16_t *)acpi_tables) =3D >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0cpu_to_le32(le32_to_cpu(*(uint16_t *)acpi_t= ables) + 1); >> + >> + =C2=A0 =C2=A0acpi_tables_len =3D allen; >> =C2=A0 =C2=A0 =C2=A0return 0; >> -out: >> - =C2=A0 =C2=A0if (acpi_tables) { >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0qemu_free(acpi_tables); >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0acpi_tables =3D NULL; >> - =C2=A0 =C2=A0} >> - =C2=A0 =C2=A0return -1; >> + >> =C2=A0} >> >> =C2=A0/* ACPI PM1a EVT */ >> diff --git a/qemu-options.hx b/qemu-options.hx >> index 82e085a..e639d5a 100644 >> --- a/qemu-options.hx >> +++ b/qemu-options.hx >> @@ -1014,12 +1014,17 @@ Enable virtio balloon device (default), optional= ly with PCI address >> =C2=A0ETEXI >> >> =C2=A0DEF("acpitable", HAS_ARG, QEMU_OPTION_acpitable, >> - =C2=A0 =C2=A0"-acpitable [sig=3Dstr][,rev=3Dn][,oem_id=3Dstr][,oem_tab= le_id=3Dstr][,oem_rev=3Dn][,asl_compiler_id=3Dstr][,asl_compiler_rev=3Dn][,= data=3Dfile1[:file2]...]\n" >> + =C2=A0 =C2=A0"-acpitable [sig=3Dstr][,rev=3Dn][,oem_id=3Dstr][,oem_tab= le_id=3Dstr][,oem_rev=3Dn][,asl_compiler_id=3Dstr][,asl_compiler_rev=3Dn][,= {data|file}=3Dfile1[:file2]...]\n" >> =C2=A0 =C2=A0 =C2=A0" =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0ACPI table description\n", QEMU_ARCH_I386) >> =C2=A0STEXI >> =C2=A0@item -acpitable [sig=3D@var{str}][,rev=3D@var{n}][,oem_id=3D@var{= str}][,oem_table_id=3D@var{str}][,oem_rev=3D@var{n}] [,asl_compiler_id=3D@v= ar{str}][,asl_compiler_rev=3D@var{n}][,data=3D@var{file1}[:@var{file2}]...] >> =C2=A0@findex -acpitable >> =C2=A0Add ACPI table with specified header fields and context from speci= fied files. >> +For file=3D, take whole ACPI table from the specified files, including = all >> +ACPI headers (possible overridden by other options). >> +For data=3D, only data >> +portion of the table is used, all header information is specified in th= e >> +command line. >> =C2=A0ETEXI >> >> =C2=A0DEF("smbios", HAS_ARG, QEMU_OPTION_smbios, > > >