[U-Boot] [PATCH 05/13] sparse: Implement storage abstraction

Maxime Ripard
2015-08-31T14:46:05Z

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 <maxime.ripard@free-electrons.com>
---
common/aboot.c | 51 +++++++++++++++++++++++++++++++++++----------------
common/fb_mmc.c | 39 +++++++++++++++++++++++++++++++++++----
include/aboot.h | 14 ++++++++++++++
3 files changed, 84 insertions(+), 20 deletions(-)

diff --git a/common/aboot.c b/common/aboot.c
index c8556d9b23f4..18ff30ee6d11 100644
--- a/common/aboot.c
+++ b/common/aboot.c
@@ -42,6 +42,13 @@
#include <part.h>
#include <sparse_format.h>

+typedef struct sparse_buffer {
+ void *data;
+ u32 length;
+ u32 repeat;
+ u16 type;
+} sparse_buffer_t;
+
static unsigned int sparse_get_chunk_data_size(sparse_header_t *sparse,
chunk_header_t *chunk)
{
@@ -247,13 +254,11 @@ static void sparse_put_data_buffer(sparse_buffer_t *buffer)
free(buffer);
}

-void write_sparse_image(block_dev_desc_t *dev_desc,
- disk_partition_t *info, const char *part_name,
- void *data, unsigned sz)
+void store_sparse_image(sparse_storage_t *storage,
+ void *storage_priv, void *data)
{
- lbaint_t blk;
- lbaint_t blkcnt;
- lbaint_t blks;
+ uint32_t blk;
+ uint32_t blkcnt;
uint32_t bytes_written = 0;
unsigned int chunk;
sparse_header_t *sparse_header;
@@ -262,14 +267,25 @@ void write_sparse_image(block_dev_desc_t *dev_desc,
uint32_t total_blocks = 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) {
fastboot_fail("sparse header issue\n");
return;
}

- /* verify sparse_header->blk_sz is an exact multiple of info->blksz */
- if (sparse_header->blk_sz % info->blksz) {
+ /*
+ * Verify that the sparse block size is a multiple of our
+ * storage backend block size
+ */
+ if (sparse_header->blk_sz % storage->block_sz) {
printf("%s: Sparse image block size issue [%u]\n",
__func__, sparse_header->blk_sz);
fastboot_fail("sparse image block size issue");
@@ -279,7 +295,7 @@ void write_sparse_image(block_dev_desc_t *dev_desc,
puts("Flashing Sparse Image\n");

/* Start processing chunks */
- blk = info->start;
+ blk = storage->start;
for (chunk = 0; chunk < sparse_header->total_chunks; chunk++) {
chunk_header = sparse_parse_chunk(sparse_header, &data);
if (!chunk_header) {
@@ -289,13 +305,13 @@ void write_sparse_image(block_dev_desc_t *dev_desc,

/* 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 (blk + blkcnt > info->start + info->size) {
+ if (blk + blkcnt > storage->start + storage->size) {
printf("%s: Request would exceed partition size!\n",
__func__);
fastboot_fail("Request would exceed partition size!");
@@ -308,10 +324,12 @@ void write_sparse_image(block_dev_desc_t *dev_desc,

buffer_blk_cnt = buffer->length / storage->block_sz;

- buffer_blks = dev_desc->block_write(dev_desc->dev, blk,
- buffer_blk_cnt, buffer->data);
+ buffer_blks = storage->write(storage,
+ storage_priv,
+ blk, buffer_blk_cnt,
+ buffer->data);
if (buffer_blks != buffer_blk_cnt) {
- printf("%s: Write %d failed " LBAFU "\n",
+ printf("%s: Write %d failed %d\n",
__func__, i, buffer_blks);
fastboot_fail("flash write failure");
return;
@@ -327,7 +345,8 @@ void write_sparse_image(block_dev_desc_t *dev_desc,

debug("Wrote %d blocks, expected to write %d blocks\n",
total_blocks, sparse_header->total_blks);
- printf("........ wrote %u bytes to '%s'\n", bytes_written, part_name);
+ printf("........ wrote %u bytes to '%s'\n", bytes_written,
+ storage->name);

if (total_blocks != sparse_header->total_blks)
fastboot_fail("sparse image write failure");
diff --git a/common/fb_mmc.c b/common/fb_mmc.c
index 0c48cf929f8f..a44627c00060 100644
--- a/common/fb_mmc.c
+++ b/common/fb_mmc.c
@@ -33,6 +33,10 @@ void fastboot_okay(const char *s)
strncat(response_str, s, RESPONSE_LEN - 4 - 1);
}

+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)
{
@@ -55,6 +59,19 @@ static int get_partition_info_efi_by_name_or_alias(block_dev_desc_t *dev_desc,
return ret;
}

+
+static unsigned 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;
+
+ return dev_desc->block_write(dev_desc->dev, offset, size, data);
+}
+
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)
@@ -126,12 +143,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);
+ }
}

void fb_mmc_erase(const char *cmd, char *response)
diff --git a/include/aboot.h b/include/aboot.h
index 30e4d36df8ba..162d81da6d9d 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;
+
+ unsigned int (*write)(struct sparse_storage *storage, void *priv,
+ unsigned int offset, unsigned int size,
+ char *data);
+} sparse_storage_t;
+
void fastboot_fail(const char *s);
void fastboot_okay(const char *s);

@@ -26,3 +37,6 @@ static inline int is_sparse_image(void *buf)
void write_sparse_image(block_dev_desc_t *dev_desc,
disk_partition_t *info, const char *part_name,
void *data, unsigned sz);
+
+void store_sparse_image(sparse_storage_t *storage, void *storage_priv,
+ void *data);
--
2.5.0