From patchwork Fri Oct 12 11:38:26 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 191104 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id BDB692C008A for ; Fri, 12 Oct 2012 22:54:25 +1100 (EST) Received: from localhost ([::1]:53998 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TMdab-00026g-FR for incoming@patchwork.ozlabs.org; Fri, 12 Oct 2012 07:39:37 -0400 Received: from eggs.gnu.org ([208.118.235.92]:33255) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TMdZr-0000XV-Qg for qemu-devel@nongnu.org; Fri, 12 Oct 2012 07:38:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TMdZl-00081Q-8K for qemu-devel@nongnu.org; Fri, 12 Oct 2012 07:38:51 -0400 Received: from 38.0.169.217.in-addr.arpa ([217.169.0.38]:57335 helo=mnementh.archaic.org.uk) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TMdZl-00080H-1B for qemu-devel@nongnu.org; Fri, 12 Oct 2012 07:38:45 -0400 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.72) (envelope-from ) id 1TMdZY-0003Hg-J8; Fri, 12 Oct 2012 12:38:32 +0100 From: Peter Maydell To: Anthony Liguori Date: Fri, 12 Oct 2012 12:38:26 +0100 Message-Id: <1350041912-12595-4-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1350041912-12595-1-git-send-email-peter.maydell@linaro.org> References: <1350041912-12595-1-git-send-email-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 217.169.0.38 Cc: qemu-devel@nongnu.org, Paul Brook Subject: [Qemu-devel] [PATCH 3/9] hw/ds1338: Fix mishandling of register pointer X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Correct several deficiencies in the handling of the register pointer: * it should wrap around after 0x3f, not 0xff * guard against the caller handing us an out of range pointer (on h/w this can never happen, because only a 7 bit value is transferred over the I2C bus) * there was confusion over whether nvram[] holds only the 56 bytes of guest-accessible NVRAM, or also the secondary registers which hold the value of the clock captured at the start of a multibyte read. Correct to consistently be the latter, by fixing the array size and the offset used for NVRAM writes. * ds1338_send was attempting to use 'data' as both the data and the register offset simultaneously, which meant that writes to any register were broken; fix to use the register pointer. Signed-off-by: Peter Maydell --- hw/ds1338.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/hw/ds1338.c b/hw/ds1338.c index d590d9c..be68140 100644 --- a/hw/ds1338.c +++ b/hw/ds1338.c @@ -12,11 +12,16 @@ #include "i2c.h" +/* Size of NVRAM including both the user-accessible area and the + * secondary register area. + */ +#define NVRAM_SIZE 64 + typedef struct { I2CSlave i2c; time_t offset; struct tm now; - uint8_t nvram[56]; + uint8_t nvram[NVRAM_SIZE]; int ptr; int addr_byte; } DS1338State; @@ -57,7 +62,7 @@ static int ds1338_recv(I2CSlave *i2c) uint8_t res; res = s->nvram[s->ptr]; - s->ptr = (s->ptr + 1) & 0xff; + s->ptr = (s->ptr + 1) & (NVRAM_SIZE - 1); return res; } @@ -65,14 +70,13 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data) { DS1338State *s = FROM_I2C_SLAVE(DS1338State, i2c); if (s->addr_byte) { - s->ptr = data; + s->ptr = data & (NVRAM_SIZE - 1); s->addr_byte = 0; return 0; } - s->nvram[s->ptr - 8] = data; - if (data < 8) { + if (s->ptr < 8) { qemu_get_timedate(&s->now, s->offset); - switch(data) { + switch(s->ptr) { case 0: /* TODO: Implement CH (stop) bit. */ s->now.tm_sec = from_bcd(data & 0x7f); @@ -109,8 +113,10 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data) break; } s->offset = qemu_timedate_diff(&s->now); + } else { + s->nvram[s->ptr] = data; } - s->ptr = (s->ptr + 1) & 0xff; + s->ptr = (s->ptr + 1) & (NVRAM_SIZE - 1); return 0; }