- add capability to "fastboot flash" with sparse format images

Signed-off-by: Steve Rae <s...@broadcom.com>
---
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 v4:
- rearranged "sparse format" support in this patchset, in order to isolate...

Changes in v3: None
Changes in v2: None

 common/fb_mmc.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 112 insertions(+), 3 deletions(-)

diff --git a/common/fb_mmc.c b/common/fb_mmc.c
index f42a115..306c102 100644
--- a/common/fb_mmc.c
+++ b/common/fb_mmc.c
@@ -1,5 +1,6 @@
 /*
- * Copyright 2014 Broadcom Corporation.
+ * Copyright TODO
+ * Portions Copyright 2014 Broadcom Corporation.
  *
  * SPDX-License-Identifier:    GPL-2.0+
  */
@@ -7,6 +8,7 @@
 #include <common.h>
 #include <fb_mmc.h>
 #include <part.h>
+#include <sparse_format.h>
 
 /* The 64 defined bytes plus \0 */
 #define RESPONSE_LEN   (64 + 1)
@@ -19,6 +21,108 @@ static void fastboot_resp(const char *s)
        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 *dev_desc,
+               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;
+       }
+
+       puts("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 = dev_desc->block_write(dev_desc->dev, blk, blkcnt,
+                                                   buf);
+                       if (blks != blkcnt) {
+                               printf("%s: Write failed " LBAFU "\n",
+                                      __func__, blks);
+                               fastboot_resp("FAILwrite 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 *dev_desc, disk_partition_t *info,
                const char *part_name, void *buffer,
                unsigned int download_bytes)
@@ -77,6 +181,11 @@ void fb_mmc_flash_write(const char *cmd, void 
*download_buffer,
                return;
        }
 
-       write_raw_image(dev_desc, &info, cmd, download_buffer,
-                       download_bytes);
+       if (is_sparse_image(download_buffer)) {
+               write_sparse_image(dev_desc, &info, cmd, download_buffer,
+                                  download_bytes);
+       } else {
+               write_raw_image(dev_desc, &info, cmd, download_buffer,
+                               download_bytes);
+       }
 }
-- 
1.8.5

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to