From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:59976) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TgKx2-0001XU-Cc for qemu-devel@nongnu.org; Wed, 05 Dec 2012 14:48:16 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TgKwy-0006is-Be for qemu-devel@nongnu.org; Wed, 05 Dec 2012 14:48:12 -0500 Received: from relay0.mail.ox.ac.uk ([129.67.1.161]:60480) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TgKwy-0006iV-5Q for qemu-devel@nongnu.org; Wed, 05 Dec 2012 14:48:08 -0500 From: Alex Horn Date: Wed, 5 Dec 2012 19:48:03 +0000 Message-Id: <1354736883-22417-1-git-send-email-alex.horn@cs.ox.ac.uk> Subject: [Qemu-devel] [PATCH 1/1] tmp105: Fix I2C protocol bug List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: peter.maydell@linaro.org, afaerber@suse.de, anthony@codemonkey.ws, Alex Horn The private buffer length field must only be incremented after the I2C frame has been transmitted. To expose this bug, assume the temperature in the TMP105 hardware model is +0.125 C (e.g. snow slush). Note that eleven bit precision is required to read this value; otherwise the reading is equal to zero centigrade (ice). Continue by considering the following I2C protocol steps: 1) Start transfer with I2C_START_SEND 2) Send byte 0x01 (i.e. configuration register) 3) Send byte 0x40 (i.e. eleven bit precision) 4) End transfer with I2C_FINISH 5) Start transfer with I2C_START_SEND 6) Send byte 0x00 (i.e. temperature register) 7) End transfer I2C_FINISH 8) Start transfer with I2C_START_RECV 9) Receive high-order byte of temperature ... In step (1), the function tmp105_tx() is called. By the conditional check !s->len and the side effect with ++, s->len is equal to 1 when step (2) begins. Thus, 0x40 is written to s->buf[1] in step (3). By definition of tmp105_write(), s->config is set to zero in step (3). Thus, when we read the higher-order byte in step (9), it is zero! In other words, the TMP105 hardware model allows us to measure 0 C (ice) even with eleven bit precision when, in fact, it should be 0.125 C (slush)! Signed-off-by: Alex Horn --- hw/tmp105.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/hw/tmp105.c b/hw/tmp105.c index 8e8dbd9..5f41a3f 100644 --- a/hw/tmp105.c +++ b/hw/tmp105.c @@ -152,7 +152,7 @@ static int tmp105_tx(I2CSlave *i2c, uint8_t data) { TMP105State *s = (TMP105State *) i2c; - if (!s->len ++) + if (s->len == 0) s->pointer = data; else { if (s->len <= 2) @@ -160,6 +160,7 @@ static int tmp105_tx(I2CSlave *i2c, uint8_t data) tmp105_write(s); } + s->len ++; return 0; } -- 1.7.6.5