From patchwork Thu Jun 26 18:45:16 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve Rae X-Patchwork-Id: 32590 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-yk0-f197.google.com (mail-yk0-f197.google.com [209.85.160.197]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 42AB2201EF for ; Thu, 26 Jun 2014 18:46:11 +0000 (UTC) Received: by mail-yk0-f197.google.com with SMTP id 19sf5558603ykq.8 for ; Thu, 26 Jun 2014 11:46:11 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id:in-reply-to :references:mime-version:cc:subject:precedence:list-id :list-unsubscribe:list-archive:list-post:list-help:list-subscribe :sender:errors-to:x-original-sender :x-original-authentication-results:mailing-list:content-type :content-transfer-encoding; bh=i9c+J4EgUZ2WaqjkA0TxE24cNwcsLCOvVXzxoc6PUUE=; b=EAdfvBUmPOxN6TPse2HX8x/ttROKneB1I6bFn0DNSe9fNw3QUtPPMNCVW3V1tNcIqy vprheR3n3p63AZtxZAGGvO77h3srKzzye//JOy+VUN2vycV8WCg84OpMuvoYiXaGz0Rx WfsPeH2gYgAr/rwX+XmcuEL7SxiGv/e8G+lffjsWWhxKfkhXPiFMKdmBGJ0sBIOgPNsl KgpVh/+tMQ0iIQBIGnJwKrD/FIcEQi8+eE4f1R5JdfK4S+cabWWxhGdseaxHcB2getGQ 7pzGxB0YZtwcA5NKPgsi7FIT9HsBhTIQrYlALMeloNFzFKfQaEgL9xrF4TemcAVzcHWf Mn+Q== X-Gm-Message-State: ALoCoQkxdULyl9vMPnw80HU6Wq4J9+m7ePe/eXsbvediJ0/Xb4VEgL3PixlqwyJhJTHTuukTy9Ba X-Received: by 10.52.184.104 with SMTP id et8mr7808804vdc.4.1403808371086; Thu, 26 Jun 2014 11:46:11 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.83.50 with SMTP id i47ls346200qgd.38.gmail; Thu, 26 Jun 2014 11:46:11 -0700 (PDT) X-Received: by 10.220.174.137 with SMTP id t9mr15604830vcz.12.1403808370998; Thu, 26 Jun 2014 11:46:10 -0700 (PDT) Received: from mail-vc0-f174.google.com (mail-vc0-f174.google.com [209.85.220.174]) by mx.google.com with ESMTPS id l10si5175018veb.2.2014.06.26.11.46.10 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 26 Jun 2014 11:46:10 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.174 as permitted sender) client-ip=209.85.220.174; Received: by mail-vc0-f174.google.com with SMTP id hy4so4033818vcb.33 for ; Thu, 26 Jun 2014 11:46:10 -0700 (PDT) X-Received: by 10.52.178.66 with SMTP id cw2mr237579vdc.93.1403808370895; Thu, 26 Jun 2014 11:46:10 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.37.5 with SMTP id tc5csp51208vcb; Thu, 26 Jun 2014 11:46:10 -0700 (PDT) X-Received: by 10.180.189.210 with SMTP id gk18mr6523413wic.66.1403808369843; Thu, 26 Jun 2014 11:46:09 -0700 (PDT) Received: from theia.denx.de (theia.denx.de. [85.214.87.163]) by mx.google.com with ESMTP id dk1si21244174wib.50.2014.06.26.11.46.09 for ; Thu, 26 Jun 2014 11:46:09 -0700 (PDT) Received-SPF: none (google.com: u-boot-bounces@lists.denx.de does not designate permitted sender hosts) client-ip=85.214.87.163; Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 4AF30A774B; Thu, 26 Jun 2014 20:46:05 +0200 (CEST) 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 fMUe7Qb21GyX; Thu, 26 Jun 2014 20:46:04 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 01755A7750; Thu, 26 Jun 2014 20:45:56 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 8C26EA7745 for ; Thu, 26 Jun 2014 20:45:50 +0200 (CEST) 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 ZOkj7Z9BszKk for ; Thu, 26 Jun 2014 20:45:47 +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-gw3-out.broadcom.com (mail-gw3-out.broadcom.com [216.31.210.64]) by theia.denx.de (Postfix) with ESMTP id 89C35A7740 for ; Thu, 26 Jun 2014 20:45:36 +0200 (CEST) X-IronPort-AV: E=Sophos;i="5.01,554,1400050800"; d="scan'208";a="36176627" Received: from irvexchcas06.broadcom.com (HELO IRVEXCHCAS06.corp.ad.broadcom.com) ([10.9.208.53]) by mail-gw3-out.broadcom.com with ESMTP; 26 Jun 2014 11:51:55 -0700 Received: from IRVEXCHSMTP2.corp.ad.broadcom.com (10.9.207.52) by IRVEXCHCAS06.corp.ad.broadcom.com (10.9.208.53) with Microsoft SMTP Server (TLS) id 14.3.174.1; Thu, 26 Jun 2014 11:45:35 -0700 Received: from mail-irva-13.broadcom.com (10.10.10.20) by IRVEXCHSMTP2.corp.ad.broadcom.com (10.9.207.52) with Microsoft SMTP Server id 14.3.174.1; Thu, 26 Jun 2014 11:45:35 -0700 Received: from mail.broadcom.com (lbrmn-vmlnx03.ric.broadcom.com [10.136.4.105]) by mail-irva-13.broadcom.com (Postfix) with ESMTP id 924FF9FB3E; Thu, 26 Jun 2014 11:45:26 -0700 (PDT) From: Steve Rae To: Rob Herring , Sebastian Siewior Date: Thu, 26 Jun 2014 11:45:16 -0700 Message-ID: <1403808318-16215-3-git-send-email-srae@broadcom.com> X-Mailer: git-send-email 1.8.5 In-Reply-To: <1403808318-16215-1-git-send-email-srae@broadcom.com> References: <1403808318-16215-1-git-send-email-srae@broadcom.com> MIME-Version: 1.0 Cc: Marek Vasut , Steve Rae , Pantelis Antoniou , u-boot@lists.denx.de, Tom Rini Subject: [U-Boot] [PATCH v2 2/4] usb/gadget: fastboot: add eMMC support for flash command X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: srae@broadcom.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.174 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 - add support for 'fastboot flash' command for eMMC devices Signed-off-by: Steve Rae --- I suspect that the "sparse image" handling (ie. the "while (remaining_chunks)" loop) has been implemented elsewhere -- I need help finding the original code to determine any licensing issues.... Thanks, Steve Changes in v2: - split large function into three - improved handling of response messages - additional partition size checking when writing sparse image common/Makefile | 5 ++ common/fb_mmc.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/fb_mmc.h | 8 +++ 3 files changed, 202 insertions(+) create mode 100644 common/fb_mmc.c create mode 100644 include/fb_mmc.h diff --git a/common/Makefile b/common/Makefile index de5cce8..daebe39 100644 --- a/common/Makefile +++ b/common/Makefile @@ -266,4 +266,9 @@ obj-$(CONFIG_IO_TRACE) += iotrace.o 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 +obj-y += fb_mmc.o +endif + CFLAGS_env_embedded.o := -Wa,--no-warn -DENV_CRC=$(shell tools/envcrc 2>/dev/null) diff --git a/common/fb_mmc.c b/common/fb_mmc.c new file mode 100644 index 0000000..4143070 --- /dev/null +++ b/common/fb_mmc.c @@ -0,0 +1,189 @@ +/* + * Copyright TODO + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +/* The 64 defined bytes plus \0 */ +#define RESPONSE_LEN (64 + 1) + +static char *response_str; + +static void fastboot_resp(const char *s) +{ + strncpy(response_str, s, RESPONSE_LEN); + response_str[RESPONSE_LEN - 1] = '\0'; +} + +static int is_sparse_image(void *buf) +{ + sparse_header_t *s_header = (sparse_header_t *)buf; + + if ((le32_to_cpu(s_header->magic) == SPARSE_HEADER_MAGIC) && + (le16_to_cpu(s_header->major_version) == 1)) + return 1; + + return 0; +} + +static void write_sparse_image(block_dev_desc_t *mmc_dev, + disk_partition_t *info, const char *part_name, + void *buffer, unsigned int download_bytes) +{ + lbaint_t blk; + lbaint_t blkcnt; + lbaint_t blks; + sparse_header_t *s_header = (sparse_header_t *)buffer; + chunk_header_t *c_header; + void *buf; + uint32_t blk_sz; + uint32_t remaining_chunks; + uint32_t bytes_written = 0; + + blk_sz = le32_to_cpu(s_header->blk_sz); + + /* verify s_header->blk_sz is exact multiple of info->blksz */ + if (blk_sz != (blk_sz & ~(info->blksz - 1))) { + printf("%s: Sparse image block size issue [%u]\n", + __func__, blk_sz); + fastboot_resp("FAILsparse image block size issue"); + return; + } + + if ((le32_to_cpu(s_header->total_blks) * blk_sz) > + (info->size * info->blksz)) { + printf("%s: Sparse image is too large for the partition\n", + __func__); + fastboot_resp("FAILsparse image is too large"); + return; + } + + printf("Flashing Sparse Image\n"); + + remaining_chunks = le32_to_cpu(s_header->total_chunks); + c_header = (chunk_header_t *)(buffer + + le16_to_cpu(s_header->file_hdr_sz)); + blk = info->start; + while (remaining_chunks) { + blkcnt = + (le32_to_cpu(c_header->chunk_sz) * blk_sz) / info->blksz; + + switch (le16_to_cpu(c_header->chunk_type)) { + case CHUNK_TYPE_RAW: + buf = (void *)c_header + + le16_to_cpu(s_header->chunk_hdr_sz); + + if (blk + blkcnt > info->start + info->size) { + printf( + "%s: Request would exceed partition size!\n", + __func__); + fastboot_resp( + "FAILRequest would exceed partition size!"); + return; + } + + blks = mmc_dev->block_write(mmc_dev->dev, blk, blkcnt, + buf); + if (blks != blkcnt) { + printf("%s: Write failed " LBAFU "\n", + __func__, blks); + fastboot_resp("FAILmmc write failure"); + return; + } + + bytes_written += blkcnt * info->blksz; + break; + + case CHUNK_TYPE_FILL: + case CHUNK_TYPE_DONT_CARE: + case CHUNK_TYPE_CRC32: + /* do nothing */ + break; + + default: + /* error */ + printf("%s: Unknown chunk type\n", __func__); + fastboot_resp("FAILunknown chunk type in sparse image"); + return; + } + + blk += blkcnt; + c_header = (chunk_header_t *)((void *)c_header + + le32_to_cpu(c_header->total_sz)); + remaining_chunks--; + } + + printf("........ wrote %u bytes to '%s'\n", bytes_written, part_name); + fastboot_resp("OKAY"); +} + +static void write_raw_image(block_dev_desc_t *mmc_dev, disk_partition_t *info, + const char *part_name, void *buffer, + unsigned int download_bytes) +{ + lbaint_t blkcnt; + lbaint_t blks; + + /* determine number of blocks to write */ + blkcnt = ((download_bytes + (info->blksz - 1)) & ~(info->blksz - 1)); + blkcnt = blkcnt / info->blksz; + + if (blkcnt > info->size) { + printf("%s: too large for partition: '%s'\n", __func__, + part_name); + fastboot_resp("FAILtoo large for partition"); + return; + } + + printf("Flashing Raw Image\n"); + + blks = mmc_dev->block_write(mmc_dev->dev, info->start, blkcnt, buffer); + if (blks != blkcnt) { + printf("%s: failed writing to mmc device %d\n", __func__, + mmc_dev->dev); + fastboot_resp("FAILfailed writing to mmc device"); + return; + } + + printf("........ wrote " LBAFU " bytes to '%s'\n", blkcnt * info->blksz, + part_name); + fastboot_resp("OKAY"); +} + +void fb_mmc_flash_write(const char *cmd, void *download_buffer, + unsigned int download_bytes, char *response) +{ + int ret; + block_dev_desc_t *mmc_dev; + disk_partition_t info; + + /* initialize the response buffer */ + response_str = response; + + mmc_dev = mmc_get_dev(CONFIG_FASTBOOT_FLASH_MMC_DEV); + if (!mmc_dev || mmc_dev->type == DEV_TYPE_UNKNOWN) { + printf("%s: invalid mmc device\n", __func__); + fastboot_resp("FAILinvalid mmc device"); + return; + } + + ret = get_partition_info_efi_by_name(mmc_dev, cmd, &info); + if (ret) { + printf("%s: cannot find partition: '%s'\n", __func__, cmd); + fastboot_resp("FAILcannot find partition"); + return; + } + + if (is_sparse_image(download_buffer)) { + write_sparse_image(mmc_dev, &info, cmd, download_buffer, + download_bytes); + } else { + write_raw_image(mmc_dev, &info, cmd, download_buffer, + download_bytes); + } +} diff --git a/include/fb_mmc.h b/include/fb_mmc.h new file mode 100644 index 0000000..1ad1d13 --- /dev/null +++ b/include/fb_mmc.h @@ -0,0 +1,8 @@ +/* + * Copyright 2014 Broadcom Corporation. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +void fb_mmc_flash_write(const char *cmd, void *download_buffer, + unsigned int download_bytes, char *response);