From patchwork Thu Oct 15 12:34:17 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 530649 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 E9A5B1402BC for ; Thu, 15 Oct 2015 23:36:02 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 2AAAC4B6E8; Thu, 15 Oct 2015 14:35:30 +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 oMj1ivaAG8OQ; Thu, 15 Oct 2015 14:35:30 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id EE4F84B6EA; Thu, 15 Oct 2015 14:35:09 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 7CA5A4B65D 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 m7JsYGlvQw-j 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 0C30E4B632 for ; Thu, 15 Oct 2015 14:34:31 +0200 (CEST) Received: by mail.free-electrons.com (Postfix, from userid 110) id E4E8A42E5; Thu, 15 Oct 2015 14:34:31 +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 AAA0742B8; Thu, 15 Oct 2015 14:34:31 +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:17 +0200 Message-Id: <1444912462-3949-10-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 09/14] fastboot: Implement NAND backend 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" So far the fastboot code was only supporting MMC-backed devices for its flashing operations (flash and erase). Add a storage backend for NAND-backed devices. Signed-off-by: Maxime Ripard --- common/Makefile | 7 +- common/fb_nand.c | 195 ++++++++++++++++++++++++++++++++++++++++ drivers/usb/gadget/f_fastboot.c | 13 ++- include/fb_nand.h | 11 +++ 4 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 common/fb_nand.c create mode 100644 include/fb_nand.h diff --git a/common/Makefile b/common/Makefile index 491c56552f40..4f6e6cea596b 100644 --- a/common/Makefile +++ b/common/Makefile @@ -274,10 +274,15 @@ obj-y += memsize.o obj-y += stdio.o # This option is not just y/n - it can have a numeric value -ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV +ifdef CONFIG_FASTBOOT_FLASH obj-y += aboot.o +ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV obj-y += fb_mmc.o endif +ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV +obj-y += fb_nand.o +endif +endif obj-$(CONFIG_CMD_BLOB) += cmd_blob.o diff --git a/common/fb_nand.c b/common/fb_nand.c new file mode 100644 index 000000000000..1c80ba9edabc --- /dev/null +++ b/common/fb_nand.c @@ -0,0 +1,195 @@ +/* + * Copyright 2014 Broadcom Corporation. + * Copyright 2015 Free Electrons. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +static char *response_str; + +struct fb_nand_sparse { + nand_info_t *nand; + struct part_info *part; +}; + +static int fb_nand_lookup(const char *partname, char *response, + nand_info_t **nand, + struct part_info **part) +{ + struct mtd_device *dev; + int ret; + u8 pnum; + + ret = mtdparts_init(); + if (ret) { + error("Cannot initialize MTD partitions\n"); + fastboot_fail(response_str, "cannot init mtdparts"); + return ret; + } + + ret = find_dev_and_part(partname, &dev, &pnum, part); + if (ret) { + error("cannot find partition: '%s'", partname); + fastboot_fail(response_str, "cannot find partition"); + return ret; + } + + if (dev->id->type != MTD_DEV_TYPE_NAND) { + error("partition '%s' is not stored on a NAND device", + partname); + fastboot_fail(response_str, "not a NAND device"); + return -EINVAL; + } + + *nand = &nand_info[dev->id->num]; + + return 0; +} + +static int _fb_nand_erase(nand_info_t *nand, struct part_info *part) +{ + nand_erase_options_t opts; + int ret; + + memset(&opts, 0, sizeof(opts)); + opts.offset = part->offset; + opts.length = part->size; + opts.quiet = 1; + + printf("Erasing blocks 0x%llx to 0x%llx\n", + part->offset, part->offset + part->size); + + ret = nand_erase_opts(nand, &opts); + if (ret) + return ret; + + printf("........ erased 0x%llx bytes from '%s'\n", + part->size, part->name); + + return 0; +} + +static int _fb_nand_write(nand_info_t *nand, struct part_info *part, + void *buffer, unsigned int offset, + unsigned int length, size_t *written) +{ + int flags = WITH_WR_VERIFY; + +#ifdef CONFIG_FASTBOOT_FLASH_NAND_TRIMFFS + flags |= WITH_DROP_FFS; +#endif + + return nand_write_skip_bad(nand, offset, &length, written, + part->size - (offset - part->offset), + buffer, flags); +} + +static int fb_nand_sparse_write(struct sparse_storage *storage, + void *priv, + unsigned int offset, + unsigned int size, + char *data) +{ + struct fb_nand_sparse *sparse = priv; + size_t written; + int ret; + + ret = _fb_nand_write(sparse->nand, sparse->part, data, + offset * storage->block_sz, + size * storage->block_sz, &written); + if (ret < 0) { + printf("Failed to write sparse chunk\n"); + return ret; + } + + return written / storage->block_sz; +} + +void fb_nand_flash_write(const char *partname, unsigned int session_id, + void *download_buffer, unsigned int download_bytes, + char *response) +{ + struct part_info *part; + nand_info_t *nand = NULL; + int ret; + + /* initialize the response buffer */ + response_str = response; + + ret = fb_nand_lookup(partname, response, &nand, &part); + if (ret) { + error("invalid NAND device"); + fastboot_fail(response_str, "invalid NAND device"); + return; + } + + if (is_sparse_image(download_buffer)) { + struct fb_nand_sparse sparse_priv; + sparse_storage_t sparse; + + sparse_priv.nand = nand; + sparse_priv.part = part; + + sparse.block_sz = nand->writesize; + sparse.start = part->offset / sparse.block_sz; + sparse.size = part->size / sparse.block_sz; + sparse.name = part->name; + sparse.write = fb_nand_sparse_write; + + ret = store_sparse_image(&sparse, &sparse_priv, session_id, + download_buffer); + } else { + printf("Flashing raw image at offset 0x%llx\n", + part->offset); + + ret = _fb_nand_write(nand, part, download_buffer, part->offset, + download_bytes, NULL); + + printf("........ wrote %u bytes to '%s'\n", + download_bytes, part->name); + } + + if (ret) { + fastboot_fail(response_str, "error writing the image"); + return; + } + + fastboot_okay(response_str, ""); +} + +void fb_nand_erase(const char *partname, char *response) +{ + struct part_info *part; + nand_info_t *nand = NULL; + int ret; + + /* initialize the response buffer */ + response_str = response; + + ret = fb_nand_lookup(partname, response, &nand, &part); + if (ret) { + error("invalid NAND device"); + fastboot_fail(response_str, "invalid NAND device"); + return; + } + + ret = _fb_nand_erase(nand, part); + if (ret) { + error("failed erasing from device %s", nand->name); + fastboot_fail(response_str, "failed erasing from device"); + return; + } + + fastboot_okay(response_str, ""); +} diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 9af0372007bb..20b6c18b9cfd 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -24,6 +24,9 @@ #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV #include #endif +#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV +#include +#endif #define FASTBOOT_VERSION "0.4" @@ -569,6 +572,11 @@ static void cb_flash(struct usb_ep *ep, struct usb_request *req) (void *)CONFIG_FASTBOOT_BUF_ADDR, download_bytes, response); #endif +#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV + fb_nand_flash_write(cmd, fastboot_flash_session_id, + (void *)CONFIG_FASTBOOT_BUF_ADDR, + download_bytes, response); +#endif fastboot_flash_session_id++; fastboot_tx_write_str(response); } @@ -577,7 +585,7 @@ static void cb_flash(struct usb_ep *ep, struct usb_request *req) static void cb_oem(struct usb_ep *ep, struct usb_request *req) { char *cmd = req->buf; -#ifdef CONFIG_FASTBOOT_FLASH +#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV if (strncmp("format", cmd + 4, 6) == 0) { char cmdbuf[32]; sprintf(cmdbuf, "gpt write mmc %x $partitions", @@ -614,6 +622,9 @@ static void cb_erase(struct usb_ep *ep, struct usb_request *req) #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV fb_mmc_erase(cmd, response); #endif +#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV + fb_nand_erase(cmd, response); +#endif fastboot_tx_write_str(response); } #endif diff --git a/include/fb_nand.h b/include/fb_nand.h new file mode 100644 index 000000000000..80ddef5656a8 --- /dev/null +++ b/include/fb_nand.h @@ -0,0 +1,11 @@ +/* + * Copyright 2014 Broadcom Corporation. + * Copyright 2015 Free Electrons. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +void fb_nand_flash_write(const char *cmd, unsigned int session_id, + void *download_buffer, unsigned int download_bytes, + char *response); +void fb_nand_erase(const char *cmd, char *response);