diff options
-rw-r--r-- | common/aboot.c | 77 | ||||
-rw-r--r-- | common/fb_mmc.c | 45 | ||||
-rw-r--r-- | include/aboot.h | 16 |
3 files changed, 104 insertions, 34 deletions
diff --git a/common/aboot.c b/common/aboot.c index 5f5fb6b62b..6c35d82269 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 b31a9fb929..c9f2ed6b58 100644 --- a/common/fb_mmc.c +++ b/common/fb_mmc.c @@ -6,6 +6,7 @@ #include <config.h> #include <common.h> +#include <errno.h> #include <fastboot.h> #include <fb_mmc.h> #include <part.h> @@ -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 18ff07a5dc..a2b0694190 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); |