From patchwork Wed Nov 28 22:38:50 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pantelis Antoniou X-Patchwork-Id: 202570 X-Patchwork-Delegate: marek.vasut@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id B6C0D2C0082 for ; Thu, 29 Nov 2012 09:39:04 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id CE4E94A0AE; Wed, 28 Nov 2012 23:39:02 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 558-uXefUbMI; Wed, 28 Nov 2012 23:39:02 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id DCC334A09E; Wed, 28 Nov 2012 23:38:59 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 2D60E4A09E for ; Wed, 28 Nov 2012 23:38:58 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id D0U4KFBLrn3K for ; Wed, 28 Nov 2012 23:38:57 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from li42-95.members.linode.com (li42-95.members.linode.com [209.123.162.95]) by theia.denx.de (Postfix) with ESMTPS id EC2334A09C for ; Wed, 28 Nov 2012 23:38:55 +0100 (CET) Received: from sles11esa.localdomain (unknown [195.97.110.117]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: panto) by li42-95.members.linode.com (Postfix) with ESMTPSA id CF0109C1BC; Wed, 28 Nov 2012 22:38:52 +0000 (UTC) From: Pantelis Antoniou To: Marek Vasut , u-boot@lists.denx.de Date: Thu, 29 Nov 2012 00:38:50 +0200 Message-Id: <1354142330-31130-1-git-send-email-panto@antoniou-consulting.com> X-Mailer: git-send-email 1.7.12 Cc: Tom Rini , Pantelis Antoniou Subject: [U-Boot] [PATCH] dfu: Handle large transfers correctly X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de The sequence number is a 16 bit counter; make sure we handle rollover correctly. This fixes the wrong transfers for large (> 256MB) images. Signed-off-by: Pantelis Antoniou --- drivers/dfu/dfu.c | 28 +++++++++++++++++++++++----- drivers/dfu/dfu_mmc.c | 3 +++ include/dfu.h | 2 ++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 1260c55..2483018 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -82,7 +82,7 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) __func__, dfu->name, buf, size, blk_seq_num, dfu->offset, dfu->i_buf - dfu->i_buf_start); - if (blk_seq_num == 0) { + if (dfu->do_init) { /* initial state */ dfu->crc = 0; dfu->offset = 0; @@ -90,6 +90,8 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) dfu->i_buf_start = dfu_buf; dfu->i_buf_end = dfu_buf + sizeof(dfu_buf); dfu->i_buf = dfu->i_buf_start; + + dfu->do_init = 0; } if (dfu->i_blk_seq_num != blk_seq_num) { @@ -97,7 +99,8 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) __func__, dfu->i_blk_seq_num, blk_seq_num); return -1; } - dfu->i_blk_seq_num++; + /* handle rollover */ + dfu->i_blk_seq_num = (dfu->i_blk_seq_num + 1) & 0xffff; /* flush buffer if overflow */ if ((dfu->i_buf + size) > dfu->i_buf_end) { @@ -106,6 +109,13 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) ret = tret; } + /* we should be in buffer now (if not then size too large) */ + if ((dfu->i_buf + size) > dfu->i_buf_end) { + printf("%s: Wrong size! [%d] [%d] - \n", + __func__, dfu->i_blk_seq_num, blk_seq_num, size); + return -1; + } + memcpy(dfu->i_buf, buf, size); dfu->i_buf += size; @@ -120,7 +130,7 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) if (size == 0) { debug("%s: DFU complete CRC32: 0x%x\n", __func__, dfu->crc); - puts("\nDownload complete\n"); + printf("\nDownload complete (CRC32 0x%04x)\n", dfu->crc); /* clear everything */ dfu->crc = 0; @@ -129,6 +139,9 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) dfu->i_buf_start = dfu_buf; dfu->i_buf_end = dfu_buf + sizeof(dfu_buf); dfu->i_buf = dfu->i_buf_start; + + dfu->do_init = 1; + } return ret = 0 ? size : ret; @@ -190,7 +203,7 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n", __func__, dfu->name, buf, size, blk_seq_num, dfu->i_buf); - if (blk_seq_num == 0) { + if (dfu->do_init) { ret = dfu->read_medium(dfu, 0, NULL, &dfu->r_left); if (ret != 0) { debug("%s: failed to get r_left\n", __func__); @@ -206,6 +219,8 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) dfu->i_buf_end = dfu_buf + sizeof(dfu_buf); dfu->i_buf = dfu->i_buf_start; dfu->b_left = 0; + + dfu->do_init = 0; } if (dfu->i_blk_seq_num != blk_seq_num) { @@ -213,7 +228,8 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) __func__, dfu->i_blk_seq_num, blk_seq_num); return -1; } - dfu->i_blk_seq_num++; + /* handle rollover */ + dfu->i_blk_seq_num = (dfu->i_blk_seq_num + 1) & 0xffff; ret = dfu_read_buffer_fill(dfu, buf, size); if (ret < 0) { @@ -232,6 +248,8 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) dfu->i_buf_end = dfu_buf + sizeof(dfu_buf); dfu->i_buf = dfu->i_buf_start; dfu->b_left = 0; + + dfu->do_init = 1; } return ret; diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index 4c8994b..906df55 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -234,5 +234,8 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s) dfu->read_medium = dfu_read_medium_mmc; dfu->write_medium = dfu_write_medium_mmc; + /* initial state */ + dfu->do_init = 1; + return 0; } diff --git a/include/dfu.h b/include/dfu.h index b662488..0ce91b7 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -90,6 +90,8 @@ struct dfu_entity { u8 *i_buf_end; long r_left; long b_left; + + unsigned int do_init : 1 }; int dfu_config_entities(char *s, char *interface, int num);