From patchwork Thu Oct 15 12:34:14 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 530644 X-Patchwork-Delegate: trini@ti.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 D1ACC1402BC for ; Thu, 15 Oct 2015 23:34:46 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 213534B666; Thu, 15 Oct 2015 14:34:42 +0200 (CEST) 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 Csl69-yh_Yvr; Thu, 15 Oct 2015 14:34:42 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id E807A4B62B; Thu, 15 Oct 2015 14:34:36 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 2A9C04B666 for ; Thu, 15 Oct 2015 14:34:32 +0200 (CEST) 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 GCo5K_6B4CMf for ; Thu, 15 Oct 2015 14:34:32 +0200 (CEST) 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 mail.free-electrons.com (down.free-electrons.com [37.187.137.238]) by theia.denx.de (Postfix) with ESMTP id 9E63C4B65B for ; Thu, 15 Oct 2015 14:34:31 +0200 (CEST) Received: by mail.free-electrons.com (Postfix, from userid 110) id 5B62442E2; Thu, 15 Oct 2015 14:34:30 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.free-electrons.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost (AToulouse-657-1-26-161.w83-193.abo.wanadoo.fr [83.193.1.161]) by mail.free-electrons.com (Postfix) with ESMTPSA id 22E1E42B8; Thu, 15 Oct 2015 14:34:30 +0200 (CEST) From: Maxime Ripard To: Hans de Goede , Ian Campbell , Marek Vasut , =?UTF-8?q?=C5=81ukasz=20Majewski?= Date: Thu, 15 Oct 2015 14:34:14 +0200 Message-Id: <1444912462-3949-7-git-send-email-maxime.ripard@free-electrons.com> X-Mailer: git-send-email 2.5.3 In-Reply-To: <1444912462-3949-1-git-send-email-maxime.ripard@free-electrons.com> References: <1444912462-3949-1-git-send-email-maxime.ripard@free-electrons.com> Cc: Thomas Petazzoni , Tom Rini , u-boot@lists.denx.de, Alexander Kaplan Subject: [U-Boot] [PATCH v2 06/14] sparse: Implement storage abstraction X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" The current sparse image parser relies heavily on the MMC layer, and doesn't allow any other kind of storage medium to be used. Rework the parser to support any kind of storage medium, as long as there is an implementation for it. Signed-off-by: Maxime Ripard Reviewed-by: Tom Rini --- common/aboot.c | 77 +++++++++++++++++++++++++++++++++++++-------------------- common/fb_mmc.c | 45 ++++++++++++++++++++++++++++++--- include/aboot.h | 16 +++++++++--- 3 files changed, 104 insertions(+), 34 deletions(-) diff --git a/common/aboot.c b/common/aboot.c index 5f5fb6b62bfa..6c35d8226903 100644 --- a/common/aboot.c +++ b/common/aboot.c @@ -58,6 +58,13 @@ static unsigned int sparse_get_chunk_data_size(sparse_header_t *sparse, return chunk->total_sz - sparse->chunk_hdr_sz; } +static unsigned int sparse_block_size_to_storage(unsigned int size, + sparse_storage_t *storage, + sparse_header_t *sparse) +{ + return size * sparse->blk_sz / storage->block_sz; +} + static bool sparse_chunk_has_buffer(chunk_header_t *chunk) { switch (chunk->chunk_type) { @@ -257,20 +264,26 @@ static void sparse_put_data_buffer(sparse_buffer_t *buffer) free(buffer); } -int write_sparse_image(block_dev_desc_t *dev_desc, - disk_partition_t *info, const char *part_name, - void *data, unsigned sz) +int store_sparse_image(sparse_storage_t *storage, + void *storage_priv, void *data) { - lbaint_t start; - lbaint_t blkcnt; unsigned int chunk, offset; sparse_header_t *sparse_header; chunk_header_t *chunk_header; sparse_buffer_t *buffer; + uint32_t start; uint32_t total_blocks = 0; uint32_t skipped = 0; int i; + debug("=== Storage ===\n"); + debug("name: %s\n", storage->name); + debug("block_size: 0x%x\n", storage->block_sz); + debug("start: 0x%x\n", storage->start); + debug("size: 0x%x\n", storage->size); + debug("write: 0x%p\n", storage->write); + debug("priv: 0x%p\n", storage_priv); + sparse_header = sparse_parse_header(&data); if (!sparse_header) { printf("sparse header issue\n"); @@ -281,7 +294,7 @@ int write_sparse_image(block_dev_desc_t *dev_desc, * Verify that the sparse block size is a multiple of our * storage backend block size */ - div_u64_rem(sparse_header->blk_sz, info->blksz, &offset); + div_u64_rem(sparse_header->blk_sz, storage->block_sz, &offset); if (offset) { printf("%s: Sparse image block size issue [%u]\n", __func__, sparse_header->blk_sz); @@ -291,8 +304,10 @@ int write_sparse_image(block_dev_desc_t *dev_desc, puts("Flashing Sparse Image\n"); /* Start processing chunks */ - start = info->start; + start = storage->start; for (chunk = 0; chunk < sparse_header->total_chunks; chunk++) { + uint32_t blkcnt; + chunk_header = sparse_parse_chunk(sparse_header, &data); if (!chunk_header) { printf("Unknown chunk type"); @@ -304,20 +319,22 @@ int write_sparse_image(block_dev_desc_t *dev_desc, * and go on parsing the rest of the chunks */ if (chunk_header->chunk_type == CHUNK_TYPE_DONT_CARE) { - skipped += chunk_header->chunk_sz; + skipped += sparse_block_size_to_storage(chunk_header->chunk_sz, + storage, + sparse_header); continue; } /* Retrieve the buffer we're going to write */ buffer = sparse_get_data_buffer(sparse_header, chunk_header, - info->blksz, &data); + storage->block_sz, &data); if (!buffer) continue; - blkcnt = (buffer->length / info->blksz) * buffer->repeat; + blkcnt = (buffer->length / storage->block_sz) * buffer->repeat; if ((start + total_blocks + blkcnt) > - (info->start + info->size)) { + (storage->start + storage->size)) { printf("%s: Request would exceed partition size!\n", __func__); return -EINVAL; @@ -325,30 +342,36 @@ int write_sparse_image(block_dev_desc_t *dev_desc, for (i = 0; i < buffer->repeat; i++) { unsigned long buffer_blk_cnt; - unsigned long buffer_blks; - - buffer_blk_cnt = buffer->length / info->blksz; - - buffer_blks = dev_desc->block_write(dev_desc->dev, - start + total_blocks, - buffer_blk_cnt, buffer->data); - if (buffer_blks != buffer_blk_cnt) { - printf("%s: Write %d failed " LBAFU "\n", - __func__, i, buffer_blks); - return -EIO; + int ret; + + buffer_blk_cnt = buffer->length / storage->block_sz; + + ret = storage->write(storage, storage_priv, + start + total_blocks, + buffer_blk_cnt, + buffer->data); + if (ret < 0) { + printf("%s: Write %d failed %d\n", + __func__, i, ret); + return ret; } - total_blocks += buffer_blk_cnt; + total_blocks += ret; } sparse_put_data_buffer(buffer); } debug("Wrote %d blocks, skipped %d, expected to write %d blocks\n", - total_blocks, skipped, sparse_header->total_blks); - printf("........ wrote %d blocks to '%s'\n", total_blocks, part_name); - - if (total_blocks != sparse_header->total_blks) { + total_blocks, skipped, + sparse_block_size_to_storage(sparse_header->total_blks, + storage, sparse_header)); + printf("........ wrote %d blocks to '%s'\n", total_blocks, + storage->name); + + if ((total_blocks + skipped) != + sparse_block_size_to_storage(sparse_header->total_blks, + storage, sparse_header)) { printf("sparse image write failure\n"); return -EIO; } diff --git a/common/fb_mmc.c b/common/fb_mmc.c index b31a9fb929c5..c9f2ed6b5863 100644 --- a/common/fb_mmc.c +++ b/common/fb_mmc.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -19,6 +20,10 @@ static char *response_str; +struct fb_mmc_sparse { + block_dev_desc_t *dev_desc; +}; + static int get_partition_info_efi_by_name_or_alias(block_dev_desc_t *dev_desc, const char *name, disk_partition_t *info) { @@ -41,6 +46,24 @@ static int get_partition_info_efi_by_name_or_alias(block_dev_desc_t *dev_desc, return ret; } + +static int fb_mmc_sparse_write(struct sparse_storage *storage, + void *priv, + unsigned int offset, + unsigned int size, + char *data) +{ + struct fb_mmc_sparse *sparse = priv; + block_dev_desc_t *dev_desc = sparse->dev_desc; + int ret; + + ret = dev_desc->block_write(dev_desc->dev, offset, size, data); + if (!ret) + return -EIO; + + return ret; +} + static void write_raw_image(block_dev_desc_t *dev_desc, disk_partition_t *info, const char *part_name, void *buffer, unsigned int download_bytes) @@ -113,12 +136,26 @@ void fb_mmc_flash_write(const char *cmd, void *download_buffer, return; } - if (is_sparse_image(download_buffer)) - write_sparse_image(dev_desc, &info, cmd, download_buffer, - download_bytes); - else + if (is_sparse_image(download_buffer)) { + struct fb_mmc_sparse sparse_priv; + sparse_storage_t sparse; + + sparse_priv.dev_desc = dev_desc; + + sparse.block_sz = info.blksz; + sparse.start = info.start; + sparse.size = info.size; + sparse.name = cmd; + sparse.write = fb_mmc_sparse_write; + + printf("Flashing sparse image at offset " LBAFU "\n", + info.start); + + store_sparse_image(&sparse, &sparse_priv, download_buffer); + } else { write_raw_image(dev_desc, &info, cmd, download_buffer, download_bytes); + } fastboot_okay(response_str, ""); } diff --git a/include/aboot.h b/include/aboot.h index 18ff07a5dc23..a2b0694190d9 100644 --- a/include/aboot.h +++ b/include/aboot.h @@ -9,6 +9,17 @@ #define ROUNDUP(x, y) (((x) + ((y) - 1)) & ~((y) - 1)) +typedef struct sparse_storage { + unsigned int block_sz; + unsigned int start; + unsigned int size; + const char *name; + + int (*write)(struct sparse_storage *storage, void *priv, + unsigned int offset, unsigned int size, + char *data); +} sparse_storage_t; + static inline int is_sparse_image(void *buf) { sparse_header_t *s_header = (sparse_header_t *)buf; @@ -20,6 +31,5 @@ static inline int is_sparse_image(void *buf) return 0; } -int write_sparse_image(block_dev_desc_t *dev_desc, - disk_partition_t *info, const char *part_name, - void *data, unsigned sz); +int store_sparse_image(sparse_storage_t *storage, void *storage_priv, + void *data);