From: John Baboval <john.baboval@virtualcomputer.com>
To: Blue Swirl <blauwirbel@gmail.com>
Cc: Isaku Yamahata <yamahata@valinux.co.jp>,
Michael Tokarev <mjt@tls.msk.ru>,
qemu-devel@nongnu.org,
Anthony Liguori <aliguori@linux.vnet.ibm.com>
Subject: Re: [Qemu-devel] [PATCH] v6 revamp acpitable parsing and allow to specify complete (headerful) table
Date: Fri, 15 Jul 2011 11:18:47 -0400 [thread overview]
Message-ID: <4E205A57.2040309@virtualcomputer.com> (raw)
In-Reply-To: <BANLkTikhWgNnKDs9i6htMHT1xV5EvvWafw@mail.gmail.com>
Is there something I can do to help take this patch the rest of the way?
I'd hate to see it die because of a style issue and a compiler warning.
-John
On 06/15/2011 02:19 PM, Blue Swirl wrote:
> On Sat, Jun 11, 2011 at 1:29 AM, Michael Tokarev<mjt@tls.msk.ru> wrote:
>> I've given up on this one. Personally 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. I
>> 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'
>
>> /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= 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<mjt@tls.msk.ru>
>>> ---
>>> hw/acpi.c | 292 ++++++++++++++++++++++++++++++++-----------------------
>>> qemu-options.hx | 7 +-
>>> 2 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 @@
>>>
>>> struct acpi_table_header
>>> {
>>> - char signature [4]; /* ACPI signature (4 ASCII characters) */
>>> + uint16_t _length; /* our length, not actual part of the hdr */
>>> + /* XXX why we have 2 length fields here? */
>>> + char sig[4]; /* ACPI signature (4 ASCII characters) */
>>> uint32_t length; /* Length of table, in bytes, including header */
>>> uint8_t revision; /* ACPI Specification minor version # */
>>> uint8_t checksum; /* To make sum of entire table == 0 */
>>> - char oem_id [6]; /* OEM identification */
>>> - char oem_table_id [8]; /* OEM table identification */
>>> + char oem_id[6]; /* OEM identification */
>>> + char oem_table_id[8]; /* OEM table identification */
>>> uint32_t oem_revision; /* OEM revision number */
>>> - char asl_compiler_id [4]; /* ASL compiler vendor ID */
>>> + char asl_compiler_id[4]; /* ASL compiler vendor ID */
>>> uint32_t asl_compiler_revision; /* ASL compiler revision number */
>>> } __attribute__((packed));
>>>
>>> +#define ACPI_TABLE_HDR_SIZE sizeof(struct acpi_table_header)
>>> +#define ACPI_TABLE_PFX_SIZE sizeof(uint16_t) /* size of the extra prefix */
>>> +
>>> +static const char dfl_hdr[ACPI_TABLE_HDR_SIZE] =
>>> + "\0\0" /* fake _length (2) */
>>> + "QEMU\0\0\0\0\1\0" /* sig (4), len(4), revno (1), csum (1) */
>>> + "QEMUQEQEMUQEMU\1\0\0\0" /* OEM id (6), table (8), revno (4) */
>>> + "QEMU\1\0\0\0" /* ASL compiler ID (4), version (4) */
>>> + ;
>>> +
>>> char *acpi_tables;
>>> size_t acpi_tables_len;
>>>
>>> @@ -45,158 +57,192 @@ static int acpi_checksum(const uint8_t *data, int len)
>>> return (-sum)& 0xff;
>>> }
>>>
>>> +/* like strncpy() but zero-fills the tail of destination */
>>> +static void strzcpy(char *dst, const char *src, size_t size)
>>> +{
>>> + size_t len = strlen(src);
>>> + if (len>= size) {
>>> + len = size;
>>> + } else {
>>> + memset(dst + len, 0, size - len);
>>> + }
>>> + memcpy(dst, src, len);
>>> +}
>>> +
>>> +/* XXX fixme: this function uses obsolete argument parsing interface */
>>> int acpi_table_add(const char *t)
>>> {
>>> - static const char *dfl_id = "QEMUQEMU";
>>> char buf[1024], *p, *f;
>>> - struct acpi_table_header acpi_hdr;
>>> unsigned long val;
>>> - uint32_t length;
>>> - struct acpi_table_header *acpi_hdr_p;
>>> - size_t off;
>>> + size_t len, start, allen;
>>> + bool has_header;
>>> + int changed;
>>> + int r;
>>> + struct acpi_table_header hdr;
>>> +
>>> + r = 0;
>>> + r |= get_param_value(buf, sizeof(buf), "data", t) ? 1 : 0;
>>> + r |= get_param_value(buf, sizeof(buf), "file", t) ? 2 : 0;
>>> + switch (r) {
>>> + case 0:
>>> + buf[0] = '\0';
> Missing 'break' or comment about fall through.
>
>>> + case 1:
>>> + has_header = false;
>>> + break;
>>> + case 2:
>>> + has_header = true;
>>> + break;
>>> + default:
>>> + fprintf(stderr, "acpitable: both data and file are specified\n");
>>> + return -1;
>>> + }
>>> +
>>> + if (!acpi_tables) {
>>> + allen = sizeof(uint16_t);
>>> + acpi_tables = qemu_mallocz(allen);
>>> + }
>>> + else {
> 'else' belongs to the previous line.
>
>>> + allen = acpi_tables_len;
>>> + }
>>> +
>>> + start = allen;
>>> + acpi_tables = qemu_realloc(acpi_tables, start + ACPI_TABLE_HDR_SIZE);
>>> + allen += has_header ? ACPI_TABLE_PFX_SIZE : ACPI_TABLE_HDR_SIZE;
>>> +
>>> + /* now read in the data files, reallocating buffer as needed */
>>> +
>>> + for (f = strtok(buf, ":"); f; f = strtok(NULL, ":")) {
>>> + int fd = open(f, O_RDONLY);
>>> +
>>> + if (fd< 0) {
>>> + fprintf(stderr, "can't open file %s: %s\n", f, strerror(errno));
>>> + return -1;
>>> + }
>>> +
>>> + for (;;) {
>>> + char data[8192];
>>> + r = read(fd, data, sizeof(data));
>>> + if (r == 0) {
>>> + break;
>>> + } else if (r> 0) {
>>> + acpi_tables = qemu_realloc(acpi_tables, allen + r);
>>> + memcpy(acpi_tables + allen, data, r);
>>> + allen += r;
>>> + } else if (errno != EINTR) {
>>> + fprintf(stderr, "can't read file %s: %s\n",
>>> + f, strerror(errno));
>>> + close(fd);
>>> + return -1;
>>> + }
>>> + }
>>> +
>>> + close(fd);
>>> + }
>>> +
>>> + /* now fill in the header fields */
>>> +
>>> + f = acpi_tables + start; /* start of the table */
>>> + changed = 0;
>>> +
>>> + /* copy the header to temp place to align the fields */
>>> + memcpy(&hdr, has_header ? f : dfl_hdr, ACPI_TABLE_HDR_SIZE);
>>> +
>>> + /* length of the table minus our prefix */
>>> + len = allen - start - ACPI_TABLE_PFX_SIZE;
>>> +
>>> + hdr._length = cpu_to_le16(len);
>>>
>>> - memset(&acpi_hdr, 0, sizeof(acpi_hdr));
>>> -
>>> if (get_param_value(buf, sizeof(buf), "sig", t)) {
>>> - strncpy(acpi_hdr.signature, buf, 4);
>>> - } else {
>>> - strncpy(acpi_hdr.signature, dfl_id, 4);
>>> + strzcpy(hdr.sig, buf, sizeof(hdr.sig));
>>> + ++changed;
>>> }
>>> +
>>> + /* length of the table including header, in bytes */
>>> + if (has_header) {
>>> + /* check if actual length is correct */
>>> + val = le32_to_cpu(hdr.length);
>>> + if (val != len) {
>>> + fprintf(stderr,
>>> + "warning: acpitable has wrong length,"
>>> + " header says %lu, actual size %u bytes\n",
>>> + val, len);
>>> + ++changed;
>>> + }
>>> + }
>>> + /* we may avoid putting length here if has_header is true */
>>> + hdr.length = cpu_to_le32(len);
>>> +
>>> if (get_param_value(buf, sizeof(buf), "rev", t)) {
>>> - val = strtoul(buf,&p, 10);
>>> - if (val> 255 || *p != '\0')
>>> - goto out;
>>> - } else {
>>> - val = 1;
>>> + val = strtoul(buf,&p, 0);
>>> + if (val> 255 || *p) {
>>> + fprintf(stderr, "acpitable: \"rev=%s\" is invalid\n", buf);
>>> + return -1;
>>> + }
>>> + hdr.revision = (uint8_t)val;
>>> + ++changed;
>>> }
>>> - acpi_hdr.revision = (int8_t)val;
>>>
>>> if (get_param_value(buf, sizeof(buf), "oem_id", t)) {
>>> - strncpy(acpi_hdr.oem_id, buf, 6);
>>> - } else {
>>> - strncpy(acpi_hdr.oem_id, dfl_id, 6);
>>> + strzcpy(hdr.oem_id, buf, sizeof(hdr.oem_id));
>>> + ++changed;
>>> }
>>>
>>> if (get_param_value(buf, sizeof(buf), "oem_table_id", t)) {
>>> - strncpy(acpi_hdr.oem_table_id, buf, 8);
>>> - } else {
>>> - strncpy(acpi_hdr.oem_table_id, dfl_id, 8);
>>> + strzcpy(hdr.oem_table_id, buf, sizeof(hdr.oem_table_id));
>>> + ++changed;
>>> }
>>>
>>> if (get_param_value(buf, sizeof(buf), "oem_rev", t)) {
>>> - val = strtol(buf,&p, 10);
>>> - if(*p != '\0')
>>> - goto out;
>>> - } else {
>>> - val = 1;
>>> + val = strtol(buf,&p, 0);
>>> + if (*p) {
>>> + fprintf(stderr, "acpitable: \"oem_rev=%s\" is invalid\n", buf);
>>> + return -1;
>>> + }
>>> + hdr.oem_revision = cpu_to_le32(val);
>>> + ++changed;
>>> }
>>> - acpi_hdr.oem_revision = cpu_to_le32(val);
>>>
>>> if (get_param_value(buf, sizeof(buf), "asl_compiler_id", t)) {
>>> - strncpy(acpi_hdr.asl_compiler_id, buf, 4);
>>> - } else {
>>> - strncpy(acpi_hdr.asl_compiler_id, dfl_id, 4);
>>> + strzcpy(hdr.asl_compiler_id, buf, sizeof(hdr.asl_compiler_id));
>>> + ++changed;
>>> }
>>>
>>> if (get_param_value(buf, sizeof(buf), "asl_compiler_rev", t)) {
>>> - val = strtol(buf,&p, 10);
>>> - if(*p != '\0')
>>> - goto out;
>>> - } else {
>>> - val = 1;
>>> - }
>>> - acpi_hdr.asl_compiler_revision = cpu_to_le32(val);
>>> -
>>> - if (!get_param_value(buf, sizeof(buf), "data", t)) {
>>> - buf[0] = '\0';
>>> - }
>>> -
>>> - length = sizeof(acpi_hdr);
>>> -
>>> - f = buf;
>>> - while (buf[0]) {
>>> - struct stat s;
>>> - char *n = strchr(f, ':');
>>> - if (n)
>>> - *n = '\0';
>>> - if(stat(f,&s)< 0) {
>>> - fprintf(stderr, "Can't stat file '%s': %s\n", f, strerror(errno));
>>> - goto out;
>>> + val = strtol(buf,&p, 0);
>>> + if (*p) {
>>> + fprintf(stderr, "acpitable: \"%s=%s\" is invalid\n",
>>> + "asl_compiler_rev", buf);
>>> + return -1;
>>> }
>>> - length += s.st_size;
>>> - if (!n)
>>> - break;
>>> - *n = ':';
>>> - f = n + 1;
>>> + hdr.asl_compiler_revision = cpu_to_le32(val);
>>> + ++changed;
>>> }
>>>
>>> - if (!acpi_tables) {
>>> - acpi_tables_len = sizeof(uint16_t);
>>> - acpi_tables = qemu_mallocz(acpi_tables_len);
>>> + if (!has_header&& !changed) {
>>> + fprintf(stderr, "warning: acpitable: no table headers are specified\n");
>>> }
>>> - acpi_tables = qemu_realloc(acpi_tables,
>>> - acpi_tables_len + sizeof(uint16_t) + length);
>>> - p = acpi_tables + acpi_tables_len;
>>> - acpi_tables_len += sizeof(uint16_t) + length;
>>> -
>>> - *(uint16_t*)p = cpu_to_le32(length);
>>> - p += sizeof(uint16_t);
>>> - memcpy(p,&acpi_hdr, sizeof(acpi_hdr));
>>> - off = sizeof(acpi_hdr);
>>> -
>>> - f = buf;
>>> - while (buf[0]) {
>>> - struct stat s;
>>> - int fd;
>>> - char *n = strchr(f, ':');
>>> - if (n)
>>> - *n = '\0';
>>> - fd = open(f, O_RDONLY);
>>> -
>>> - if(fd< 0)
>>> - goto out;
>>> - if(fstat(fd,&s)< 0) {
>>> - close(fd);
>>> - goto out;
>>> - }
>>>
>>> - /* off< length is necessary because file size can be changed
>>> - under our foot */
>>> - while(s.st_size&& off< length) {
>>> - int r;
>>> - r = read(fd, p + off, s.st_size);
>>> - if (r> 0) {
>>> - off += r;
>>> - s.st_size -= r;
>>> - } else if ((r< 0&& errno != EINTR) || r == 0) {
>>> - close(fd);
>>> - goto out;
>>> - }
>>> - }
>>>
>>> - close(fd);
>>> - if (!n)
>>> - break;
>>> - f = n + 1;
>>> - }
>>> - if (off< length) {
>>> - /* don't pass random value in process to guest */
>>> - memset(p + off, 0, length - off);
>>> + /* now calculate checksum of the table, complete with the header */
>>> + /* we may as well leave checksum intact if has_header is true */
>>> + /* alternatively there may be a way to set cksum to a given value */
>>> + hdr.checksum = 0; /* for checksum calculation */
>>> +
>>> + /* put header back */
>>> + memcpy(f,&hdr, sizeof(hdr));
>>> +
>>> + if (changed || !has_header || 1) {
>>> + ((struct acpi_table_header *)f)->checksum =
>>> + acpi_checksum((uint8_t *)f + ACPI_TABLE_PFX_SIZE, len);
>>> }
>>>
>>> - acpi_hdr_p = (struct acpi_table_header*)p;
>>> - acpi_hdr_p->length = cpu_to_le32(length);
>>> - acpi_hdr_p->checksum = acpi_checksum((uint8_t*)p, length);
>>> /* increase number of tables */
>>> - (*(uint16_t*)acpi_tables) =
>>> - cpu_to_le32(le32_to_cpu(*(uint16_t*)acpi_tables) + 1);
>>> + (*(uint16_t *)acpi_tables) =
>>> + cpu_to_le32(le32_to_cpu(*(uint16_t *)acpi_tables) + 1);
>>> +
>>> + acpi_tables_len = allen;
>>> return 0;
>>> -out:
>>> - if (acpi_tables) {
>>> - qemu_free(acpi_tables);
>>> - acpi_tables = NULL;
>>> - }
>>> - return -1;
>>> +
>>> }
>>>
>>> /* 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), optionally with PCI address
>>> ETEXI
>>>
>>> DEF("acpitable", HAS_ARG, QEMU_OPTION_acpitable,
>>> - "-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"
>>> + "-acpitable [sig=str][,rev=n][,oem_id=str][,oem_table_id=str][,oem_rev=n][,asl_compiler_id=str][,asl_compiler_rev=n][,{data|file}=file1[:file2]...]\n"
>>> " ACPI table description\n", QEMU_ARCH_I386)
>>> STEXI
>>> @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}]...]
>>> @findex -acpitable
>>> Add ACPI table with specified header fields and context from specified files.
>>> +For file=, take whole ACPI table from the specified files, including all
>>> +ACPI headers (possible overridden by other options).
>>> +For data=, only data
>>> +portion of the table is used, all header information is specified in the
>>> +command line.
>>> ETEXI
>>>
>>> DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
>>
>>
next prev parent reply other threads:[~2011-07-15 15:19 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-06-06 8:35 [Qemu-devel] [PATCH] v6 revamp acpitable parsing and allow to specify complete (headerful) table Michael Tokarev
2011-06-10 22:29 ` Michael Tokarev
2011-06-13 3:38 ` Isaku Yamahata
2011-06-15 18:19 ` Blue Swirl
2011-07-06 22:41 ` John Baboval
2011-07-15 15:18 ` John Baboval [this message]
2011-07-15 16:51 ` Blue Swirl
2011-07-29 1:49 ` Isaku Yamahata
2011-07-29 5:51 ` Michael Tokarev
2011-07-30 9:40 ` Blue Swirl
2011-07-30 16:37 ` John Baboval
-- strict thread matches above, loose matches on Subject: below --
2011-06-06 8:37 Michael Tokarev
2013-01-17 9:50 ` TeLeMan
2013-01-17 10:49 ` Michael Tokarev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4E205A57.2040309@virtualcomputer.com \
--to=john.baboval@virtualcomputer.com \
--cc=aliguori@linux.vnet.ibm.com \
--cc=blauwirbel@gmail.com \
--cc=mjt@tls.msk.ru \
--cc=qemu-devel@nongnu.org \
--cc=yamahata@valinux.co.jp \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).